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.

946 lines
26 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: perfsuite.cpp
  3. *
  4. * Copyright (c) 1991-1999 Microsoft Corporation
  5. *
  6. * Contains the test prototypes and includes
  7. *
  8. \**************************************************************************/
  9. #include "perftest.h"
  10. #include <winuser.h>
  11. /***************************************************************************\
  12. * TestSuite::TestSuite
  13. *
  14. \***************************************************************************/
  15. TestSuite::TestSuite()
  16. {
  17. }
  18. /***************************************************************************\
  19. * TestSuite::~TestSuite
  20. *
  21. \***************************************************************************/
  22. TestSuite::~TestSuite()
  23. {
  24. }
  25. /***************************************************************************\
  26. * TestSuite::InitializeDestination
  27. *
  28. * Create the destination to be used by the tests. Could be a particular
  29. * format for the screen, a bitmap, or a DIB.
  30. *
  31. * Returns:
  32. *
  33. * *bitmapResult - if a GDI+ Bitmap is to be used (use g.GetHDC() to draw
  34. * to via GDI)
  35. * *hbitmapResult - if a GDI bitmap is to be used (use Graphics(hdc) to
  36. * draw to via GDI+)
  37. * both NULL - if the screen is to be used
  38. *
  39. \***************************************************************************/
  40. BOOL
  41. TestSuite::InitializeDestination(
  42. DestinationType destinationIndex,
  43. Bitmap **bitmapResult,
  44. HBITMAP *hbitmapResult
  45. )
  46. {
  47. Graphics *g = NULL;
  48. HDC hdc = 0;
  49. INT screenDepth = 0;
  50. PixelFormat bitmapFormat = PixelFormatMax;
  51. ULONG *bitfields;
  52. Bitmap *bitmap;
  53. HBITMAP hbitmap;
  54. union
  55. {
  56. BITMAPINFO bitmapInfo;
  57. BYTE padding[sizeof(BITMAPINFO) + 3*sizeof(RGBQUAD)];
  58. };
  59. // Clear all state remembered or returned:
  60. ModeSet = FALSE;
  61. bitmap = NULL;
  62. hbitmap = NULL;
  63. HalftonePalette = NULL;
  64. // Initialize our DIB format in case we use it:
  65. RtlZeroMemory(&bitmapInfo, sizeof(bitmapInfo));
  66. bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  67. bitmapInfo.bmiHeader.biWidth = TestWidth;
  68. bitmapInfo.bmiHeader.biHeight = TestHeight;
  69. bitmapInfo.bmiHeader.biPlanes = 1;
  70. bitfields = reinterpret_cast<ULONG*>(&bitmapInfo.bmiColors[0]);
  71. // First handle any destinations that need to change the color depth:
  72. switch (destinationIndex)
  73. {
  74. case Destination_Screen_Current:
  75. break;
  76. case Destination_Screen_800_600_8bpp_HalftonePalette:
  77. HalftonePalette = DllExports::GdipCreateHalftonePalette();
  78. if (!HalftonePalette)
  79. {
  80. return FALSE;
  81. }
  82. screenDepth = 8;
  83. break;
  84. case Destination_Screen_800_600_8bpp_DefaultPalette:
  85. screenDepth = 8;
  86. break;
  87. case Destination_Screen_800_600_16bpp:
  88. screenDepth = 16;
  89. break;
  90. case Destination_Screen_800_600_24bpp:
  91. screenDepth = 24;
  92. break;
  93. case Destination_Screen_800_600_32bpp:
  94. screenDepth = 32;
  95. break;
  96. case Destination_CompatibleBitmap_8bpp:
  97. // We want to emulate a compatible bitmap at 8bpp. Because of palette
  98. // issues, we really have to switch to 8bpp mode to do that.
  99. screenDepth = 8;
  100. break;
  101. case Destination_DIB_15bpp:
  102. bitmapInfo.bmiHeader.biBitCount = 16;
  103. bitmapInfo.bmiHeader.biCompression = BI_BITFIELDS;
  104. bitfields[0] = 0x7c00;
  105. bitfields[1] = 0x03e0;
  106. bitfields[2] = 0x001f;
  107. break;
  108. case Destination_DIB_16bpp:
  109. bitmapInfo.bmiHeader.biBitCount = 16;
  110. bitmapInfo.bmiHeader.biCompression = BI_BITFIELDS;
  111. bitfields[0] = 0xf800;
  112. bitfields[1] = 0x07e0;
  113. bitfields[2] = 0x001f;
  114. break;
  115. case Destination_DIB_24bpp:
  116. bitmapInfo.bmiHeader.biBitCount = 24;
  117. bitmapInfo.bmiHeader.biCompression = BI_RGB;
  118. break;
  119. case Destination_DIB_32bpp:
  120. bitmapInfo.bmiHeader.biBitCount = 32;
  121. bitmapInfo.bmiHeader.biCompression = BI_RGB;
  122. break;
  123. case Destination_Bitmap_32bpp_ARGB:
  124. bitmapFormat = PixelFormat32bppARGB;
  125. break;
  126. case Destination_Bitmap_32bpp_PARGB:
  127. bitmapFormat = PixelFormat32bppPARGB;
  128. break;
  129. default:
  130. return FALSE;
  131. }
  132. // Now that we've figured out what to do, actually create our stuff:
  133. if (bitmapInfo.bmiHeader.biBitCount != 0)
  134. {
  135. // It's a DIB:
  136. VOID* drawBits;
  137. HDC hdcScreen = GetDC(NULL);
  138. hbitmap = CreateDIBSection(hdcScreen,
  139. &bitmapInfo,
  140. DIB_RGB_COLORS,
  141. (VOID**) &drawBits,
  142. NULL,
  143. 0);
  144. ReleaseDC(NULL, hdcScreen);
  145. if (!hbitmap)
  146. return(FALSE);
  147. }
  148. else if (bitmapFormat != PixelFormatMax)
  149. {
  150. // It's a Bitmap:
  151. bitmap = new Bitmap(TestWidth, TestHeight, bitmapFormat);
  152. if (!bitmap)
  153. return(FALSE);
  154. }
  155. else
  156. {
  157. // It's to the screen (or a weird 8bpp compatible bitmap):
  158. if (screenDepth != 0)
  159. {
  160. // We have to do a mode change:
  161. DEVMODE devMode;
  162. devMode.dmSize = sizeof(DEVMODE);
  163. devMode.dmBitsPerPel = screenDepth;
  164. devMode.dmPelsWidth = TestWidth;
  165. devMode.dmPelsHeight = TestHeight;
  166. devMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
  167. // Note that we invoke CDS_FULLSCREEN to tell the system that
  168. // the mode change is temporary (and so that User won't resize
  169. // all the windows on the desktop):
  170. if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN)
  171. != DISP_CHANGE_SUCCESSFUL)
  172. {
  173. return(FALSE);
  174. }
  175. // Remember that the mode was set:
  176. ModeSet = TRUE;
  177. // Wait several seconds to allow other OS threads to page in and
  178. // repaint the task bar, etc. We don't want that polluting our
  179. // perf numbers.
  180. Sleep(5000);
  181. }
  182. // Handle that 8bpp comaptible bitmap special case:
  183. if (destinationIndex == Destination_CompatibleBitmap_8bpp)
  184. {
  185. HDC hdcScreen = GetDC(NULL);
  186. hbitmap = CreateCompatibleBitmap(hdcScreen, TestWidth, TestHeight);
  187. ReleaseDC(NULL, hdcScreen);
  188. if (!hbitmap)
  189. return(FALSE);
  190. }
  191. }
  192. *hbitmapResult = hbitmap;
  193. *bitmapResult = bitmap;
  194. return(TRUE);
  195. }
  196. /***************************************************************************\
  197. * TestSuite::UninitializeDestination
  198. *
  199. \***************************************************************************/
  200. VOID
  201. TestSuite::UninitializeDestination(
  202. DestinationType destinationIndex,
  203. Bitmap *bitmap,
  204. HBITMAP hbitmap
  205. )
  206. {
  207. if (ModeSet)
  208. {
  209. ChangeDisplaySettings(NULL, 0);
  210. }
  211. if (HalftonePalette)
  212. {
  213. DeleteObject(HalftonePalette);
  214. }
  215. DeleteObject(hbitmap);
  216. delete bitmap;
  217. }
  218. /***************************************************************************\
  219. * TestSuite::InitializeApi
  220. *
  221. * If 'Api_GdiPlus', returns a 'Graphics*' that can be used to render to
  222. * the specified surface.
  223. *
  224. * If 'Api_Gdi', returns an 'HDC' that can be use to render to the specified
  225. * surface.
  226. *
  227. * The surface is tried in the following order:
  228. *
  229. * 1. Bitmap* (if non-NULL)
  230. * 2. HBITMAP (if non-NULL)
  231. * 3. HWND
  232. *
  233. \***************************************************************************/
  234. BOOL
  235. TestSuite::InitializeApi(
  236. ApiType apiIndex,
  237. Bitmap *bitmap,
  238. HBITMAP hbitmap,
  239. HWND hwnd,
  240. Graphics **gResult,
  241. HDC *hdcResult)
  242. {
  243. Graphics *g = NULL;
  244. HDC hdc = NULL;
  245. OldPalette = NULL;
  246. if (bitmap != NULL)
  247. {
  248. g = new Graphics(bitmap);
  249. if (!g)
  250. return(FALSE);
  251. if (apiIndex == Api_Gdi)
  252. {
  253. hdc = g->GetHDC();
  254. if (!hdc)
  255. {
  256. delete g;
  257. return(FALSE);
  258. }
  259. }
  260. }
  261. else if (hbitmap != NULL)
  262. {
  263. HDC hdcScreen = GetDC(hwnd);
  264. hdc = CreateCompatibleDC(hdcScreen);
  265. SelectObject(hdc, hbitmap);
  266. ReleaseDC(hwnd, hdcScreen);
  267. if (apiIndex == Api_GdiPlus)
  268. {
  269. g = new Graphics(hdc);
  270. if (!g)
  271. {
  272. DeleteObject(hdc);
  273. return(FALSE);
  274. }
  275. }
  276. }
  277. else
  278. {
  279. hdc = GetDC(hwnd);
  280. if (!hdc)
  281. return(FALSE);
  282. if (HalftonePalette)
  283. {
  284. OldPalette = SelectPalette(hdc, HalftonePalette, FALSE);
  285. RealizePalette(hdc);
  286. }
  287. if (apiIndex == Api_GdiPlus)
  288. {
  289. g = new Graphics(hdc);
  290. if (!g)
  291. return(FALSE);
  292. }
  293. }
  294. *gResult = g;
  295. *hdcResult = hdc;
  296. return(TRUE);
  297. }
  298. /***************************************************************************\
  299. * TestSuite::UninitializeApi
  300. *
  301. \***************************************************************************/
  302. VOID
  303. TestSuite::UninitializeApi(
  304. ApiType apiIndex,
  305. Bitmap *bitmap,
  306. HBITMAP hbitmap,
  307. HWND hwnd,
  308. Graphics *g,
  309. HDC hdc)
  310. {
  311. if (bitmap != NULL)
  312. {
  313. if (apiIndex == Api_Gdi)
  314. g->ReleaseHDC(hdc);
  315. delete g;
  316. }
  317. else if (hbitmap != NULL)
  318. {
  319. if (apiIndex == Api_GdiPlus)
  320. delete g;
  321. DeleteObject(hdc);
  322. }
  323. else
  324. {
  325. if (apiIndex == Api_GdiPlus)
  326. delete g;
  327. if (OldPalette)
  328. {
  329. SelectPalette(hdc, OldPalette, FALSE);
  330. OldPalette = NULL;
  331. }
  332. ReleaseDC(hwnd, hdc);
  333. }
  334. }
  335. /***************************************************************************\
  336. * TestSuite::InitializeState
  337. *
  338. \***************************************************************************/
  339. BOOL
  340. TestSuite::InitializeState(
  341. ApiType apiIndex,
  342. StateType stateIndex,
  343. Graphics *g,
  344. HDC hdc)
  345. {
  346. if (apiIndex == Api_GdiPlus)
  347. {
  348. SavedState = g->Save();
  349. if (!SavedState)
  350. return(FALSE);
  351. switch (stateIndex)
  352. {
  353. case State_Antialias:
  354. g->SetSmoothingMode(SmoothingModeAntiAlias);
  355. g->SetTextRenderingHint(TextRenderingHintAntiAlias);
  356. break;
  357. }
  358. }
  359. else
  360. {
  361. // Do stuff to 'hdc'
  362. }
  363. return(TRUE);
  364. }
  365. /***************************************************************************\
  366. * TestSuite::UninitializeState
  367. *
  368. \***************************************************************************/
  369. VOID
  370. TestSuite::UninitializeState(
  371. ApiType apiIndex,
  372. StateType stateIndex,
  373. Graphics *g,
  374. HDC hdc)
  375. {
  376. if (apiIndex == Api_GdiPlus)
  377. {
  378. g->Restore(SavedState);
  379. }
  380. else
  381. {
  382. // Do stuff to 'hdc'
  383. }
  384. }
  385. /***************************************************************************\
  386. * TestSuite::Run
  387. *
  388. \***************************************************************************/
  389. void TestSuite::Run(HWND hwnd)
  390. {
  391. INT i;
  392. Graphics *g;
  393. HDC hdc;
  394. INT destinationIndex;
  395. INT apiIndex;
  396. INT stateIndex;
  397. INT testIndex;
  398. TCHAR string[2048];
  399. Bitmap *bitmap;
  400. HBITMAP hbitmap;
  401. CurrentTestIndex=0;
  402. // Maximize the window:
  403. ShowWindow(hwnd, SW_MAXIMIZE);
  404. // Zero out the results matrix
  405. for (i = 0; i < ResultCount(); i++)
  406. {
  407. ResultsList[i].Score = 0;
  408. }
  409. // Go through the matrix of tests to find stuff to run
  410. for (destinationIndex = 0;
  411. destinationIndex < Destination_Count;
  412. destinationIndex++)
  413. {
  414. if (!DestinationList[destinationIndex].Enabled)
  415. continue;
  416. if (!InitializeDestination((DestinationType) destinationIndex, &bitmap, &hbitmap))
  417. continue;
  418. for (apiIndex = 0;
  419. apiIndex < Api_Count;
  420. apiIndex++)
  421. {
  422. if (!ApiList[apiIndex].Enabled)
  423. continue;
  424. if (!InitializeApi((ApiType) apiIndex, bitmap, hbitmap, hwnd, &g, &hdc))
  425. continue;
  426. for (stateIndex = 0;
  427. stateIndex < State_Count;
  428. stateIndex++)
  429. {
  430. if (!StateList[stateIndex].Enabled)
  431. continue;
  432. if (!InitializeState((ApiType) apiIndex, (StateType) stateIndex, g, hdc))
  433. continue;
  434. for (testIndex = 0;
  435. testIndex < Test_Count;
  436. testIndex++)
  437. {
  438. if (!TestList[testIndex].Enabled)
  439. continue;
  440. _stprintf(string,
  441. _T("[%s] [%s] [%s] [%s]"),
  442. ApiList[apiIndex].Description,
  443. DestinationList[destinationIndex].Description,
  444. StateList[stateIndex].Description,
  445. TestList[testIndex].TestEntry->Description);
  446. SetWindowText(hwnd, string);
  447. if (Icecap && FoundIcecap)
  448. {
  449. // Save the test information so that we can
  450. // add it to the profile
  451. CurrentTestIndex++;
  452. #if UNICODE
  453. WideCharToMultiByte(
  454. CP_ACP,
  455. 0,
  456. string,
  457. -1,
  458. CurrentTestDescription,
  459. 2048,
  460. NULL,
  461. NULL);
  462. #else
  463. strncpy(CurrentTestDescription, string, 2048);
  464. #endif
  465. }
  466. // Woo hoo, everything is now set up and we're ready
  467. // to run a test!
  468. if (apiIndex == Api_GdiPlus)
  469. {
  470. GraphicsState oldState = g->Save();
  471. ResultsList[ResultIndex(destinationIndex,
  472. apiIndex,
  473. stateIndex,
  474. testIndex)].Score
  475. = TestList[testIndex].TestEntry->Function(g, NULL);
  476. g->Restore(oldState);
  477. }
  478. else
  479. {
  480. SaveDC(hdc);
  481. ResultsList[ResultIndex(destinationIndex,
  482. apiIndex,
  483. stateIndex,
  484. testIndex)].Score
  485. = TestList[testIndex].TestEntry->Function(NULL, hdc);
  486. RestoreDC(hdc, -1);
  487. }
  488. // Copy the result to the screen if it was from a bitmap:
  489. if (bitmap)
  490. {
  491. Graphics gScreen(hwnd);
  492. gScreen.DrawImage(bitmap, 0, 0);
  493. }
  494. else if (hbitmap)
  495. {
  496. // This will use the source 'hdc', which may have a
  497. // transform set on it. Oh well!
  498. HDC hdcScreen = GetDC(hwnd);
  499. BitBlt(hdcScreen, 0, 0, TestWidth, TestHeight, hdc, 0, 0, SRCCOPY);
  500. ReleaseDC(hwnd, hdcScreen);
  501. }
  502. }
  503. UninitializeState((ApiType) apiIndex, (StateType) stateIndex, g, hdc);
  504. }
  505. UninitializeApi((ApiType) apiIndex, bitmap, hbitmap, hwnd, g, hdc);
  506. }
  507. UninitializeDestination((DestinationType) destinationIndex, bitmap, hbitmap);
  508. }
  509. // We're done!
  510. CreatePerformanceReport(ResultsList, ExcelOut);
  511. }
  512. /******************************Public*Routine******************************\
  513. * bFillBitmapInfo
  514. *
  515. * Fills in the fields of a BITMAPINFO so that we can create a bitmap
  516. * that matches the format of the display.
  517. *
  518. * This is done by creating a compatible bitmap and calling GetDIBits
  519. * to return the color masks. This is done with two calls. The first
  520. * call passes in biBitCount = 0 to GetDIBits which will fill in the
  521. * base BITMAPINFOHEADER data. The second call to GetDIBits (passing
  522. * in the BITMAPINFO filled in by the first call) will return the color
  523. * table or bitmasks, as appropriate.
  524. *
  525. * Returns:
  526. * TRUE if successful, FALSE otherwise.
  527. *
  528. * History:
  529. *
  530. * 20-Jan-2000 [gilmanw]
  531. * Removed code to set color table for 8bpp and less DIBs since calling
  532. * code will not create such DIBs.
  533. *
  534. * 07-Jun-1995 -by- Gilman Wong [gilmanw]
  535. * Wrote it.
  536. \**************************************************************************/
  537. static BOOL
  538. bFillBitmapInfo(HDC hdc, BITMAPINFO *pbmi)
  539. {
  540. HBITMAP hbm;
  541. BOOL bRet = FALSE;
  542. //
  543. // Create a dummy bitmap from which we can query color format info
  544. // about the device surface.
  545. //
  546. if ( (hbm = CreateCompatibleBitmap(hdc, 1, 1)) != NULL )
  547. {
  548. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  549. //
  550. // Call first time to fill in BITMAPINFO header.
  551. //
  552. GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
  553. if ( pbmi->bmiHeader.biCompression == BI_BITFIELDS )
  554. {
  555. //
  556. // Call a second time to get the color masks.
  557. // It's a GetDIBits Win32 "feature".
  558. //
  559. GetDIBits(hdc, hbm, 0, pbmi->bmiHeader.biHeight, NULL, pbmi,
  560. DIB_RGB_COLORS);
  561. }
  562. bRet = TRUE;
  563. DeleteObject(hbm);
  564. }
  565. return bRet;
  566. }
  567. /******************************Public*Routine******************************\
  568. * CreateCompatibleDIB2
  569. *
  570. * Create a DIB section with a optimal format w.r.t. the specified device.
  571. *
  572. * Parameters
  573. *
  574. * hdc
  575. *
  576. * Specifies display DC used to determine format. Must be a direct DC
  577. * (not an info or memory DC).
  578. *
  579. * width
  580. *
  581. * Specifies the width of the bitmap.
  582. *
  583. * height
  584. *
  585. * Specifies the height of the bitmap.
  586. *
  587. * Return Value
  588. *
  589. * The return value is the handle to the bitmap created. If the function
  590. * fails, the return value is NULL.
  591. *
  592. * Comments
  593. *
  594. * For devices that are <= 8bpp, a normal compatible bitmap is
  595. * created (i.e., CreateCompatibleBitmap is called). I have a
  596. * different version of this function that will create <= 8bpp
  597. * DIBs. However, DIBs have the property that their color table
  598. * has precedence over the palette selected into the DC whereas
  599. * a bitmap from CreateCompatibleBitmap uses the palette selected
  600. * into the DC. Therefore, in the interests of keeping this
  601. * version as close to CreateCompatibleBitmap as possible, I'll
  602. * revert to CreateCompatibleBitmap for 8bpp or less.
  603. *
  604. * History:
  605. * 19-Jan-2000 [gilmanw]
  606. * Adapted original "fastdib" version for maximum compatibility with
  607. * CreateCompatibleBitmap.
  608. *
  609. * 23-Jan-1996 -by- Gilman Wong [gilmanw]
  610. * Wrote it.
  611. \**************************************************************************/
  612. HBITMAP
  613. CreateCompatibleDIB2(HDC hdc, int width, int height)
  614. {
  615. HBITMAP hbmRet = (HBITMAP) NULL;
  616. BYTE aj[sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255)];
  617. BITMAPINFO *pbmi = (BITMAPINFO *) aj;
  618. //
  619. // Redirect 8 bpp or lower to CreateCompatibleBitmap.
  620. //
  621. if ( (GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES)) <= 8 )
  622. {
  623. return CreateCompatibleBitmap(hdc, width, height);
  624. }
  625. //
  626. // Validate hdc.
  627. //
  628. if ( GetObjectType(hdc) != OBJ_DC )
  629. {
  630. return hbmRet;
  631. }
  632. memset(aj, 0, sizeof(aj));
  633. if ( bFillBitmapInfo(hdc, pbmi) )
  634. {
  635. VOID *pvBits;
  636. //
  637. // Change bitmap size to match specified dimensions.
  638. //
  639. pbmi->bmiHeader.biWidth = width;
  640. pbmi->bmiHeader.biHeight = height;
  641. if (pbmi->bmiHeader.biCompression == BI_RGB)
  642. {
  643. pbmi->bmiHeader.biSizeImage = 0;
  644. }
  645. else
  646. {
  647. if ( pbmi->bmiHeader.biBitCount == 16 )
  648. pbmi->bmiHeader.biSizeImage = width * height * 2;
  649. else if ( pbmi->bmiHeader.biBitCount == 32 )
  650. pbmi->bmiHeader.biSizeImage = width * height * 4;
  651. else
  652. pbmi->bmiHeader.biSizeImage = 0;
  653. }
  654. pbmi->bmiHeader.biClrUsed = 0;
  655. pbmi->bmiHeader.biClrImportant = 0;
  656. //
  657. // Create the DIB section. Let Win32 allocate the memory and return
  658. // a pointer to the bitmap surface.
  659. //
  660. hbmRet = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, &pvBits, NULL, 0);
  661. }
  662. return hbmRet;
  663. }
  664. ////////////////////////////////////////////////////////////////////////
  665. //
  666. // Timer Utility Functions
  667. //
  668. ////////////////////////////////////////////////////////////////////////
  669. LONGLONG StartCounter; // Timer global, to be set by StartTimer()
  670. LONGLONG MinimumCount; // Minimum number of performance counter ticks
  671. // that must elapse before a test is considered
  672. // 'done'
  673. LONGLONG CountsPerSecond; // Frequency of the performance counter
  674. UINT Iterations; // Timer global, to be set by StartTimer() and
  675. // incremented for every call to EndTimer()
  676. UINT MinIterations; // Minimum number of iterations of the test to
  677. // be done
  678. /***************************************************************************\
  679. * StartTimer
  680. *
  681. * Called by timing routine to start the timer.
  682. *
  683. \***************************************************************************/
  684. void StartTimer()
  685. {
  686. if (Icecap && FoundIcecap)
  687. {
  688. ICStartProfile(PROFILE_GLOBALLEVEL, PROFILE_CURRENTID);
  689. ICCommentMarkProfile(CurrentTestIndex, CurrentTestDescription);
  690. }
  691. // Disable the cursor so that it doesn't interfere with the timing:
  692. ShowCursor(FALSE);
  693. if (TestRender)
  694. {
  695. // Rig it so that we do only one iteration of the test.
  696. MinIterations = 0;
  697. MinimumCount = 0;
  698. }
  699. else
  700. {
  701. // Somewhat randomly choose 1 second as the minimum counter time:
  702. QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&CountsPerSecond));
  703. MinimumCount = CountsPerSecond;
  704. // Okay, start timing!
  705. Iterations = 0;
  706. QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&StartCounter));
  707. }
  708. }
  709. /***************************************************************************\
  710. * EndTimer
  711. *
  712. * Called by timing routine to see if it's okay to stop timing. Timing
  713. * can stop if 2 conditions are satisfied:
  714. *
  715. * 1. We've gone the minimum time duration (to ensure that we good
  716. * good accuracy from the timer functions we're using)
  717. * 2. We've done the minimum number of iterations (to ensure, if the
  718. * routine being timed is very very slow, that we do more than
  719. * one iteration)
  720. *
  721. \***************************************************************************/
  722. BOOL EndTimer()
  723. {
  724. LONGLONG counter;
  725. // Always do at least MIN_ITERATIONS iterations (and only check
  726. // the timer that frequently as well):
  727. Iterations++;
  728. if (Iterations & MinIterations)
  729. return(FALSE);
  730. // Query the performance counter, and bail if for some bizarre reason
  731. // this computer doesn't support a high resolution timer (which I think
  732. // all do now-a-days):
  733. if (!QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&counter)))
  734. return(TRUE);
  735. // Ensure that we get good timer accuracy by going for the minimum
  736. // amount of time:
  737. if ((counter - StartCounter) <= MinimumCount)
  738. return(FALSE);
  739. ShowCursor(TRUE);
  740. if (Icecap && FoundIcecap)
  741. {
  742. ICStopProfile(PROFILE_GLOBALLEVEL, PROFILE_CURRENTID);
  743. }
  744. // Okay, you can stop timing!
  745. return(TRUE);
  746. }
  747. /***************************************************************************\
  748. * GetTimer
  749. *
  750. * Should only be called after EndTimer() returns TRUE. Returns the
  751. * time in seconds, and the number of iterations benchmarked.
  752. *
  753. \***************************************************************************/
  754. void GetTimer(float* seconds, UINT* iterations)
  755. {
  756. LONGLONG counter;
  757. // Note that we re-check the timer here to account for any
  758. // flushes that the caller may have needed to have done after
  759. // the EndTimer() call:
  760. QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&counter));
  761. if ((TestRender) || (CountsPerSecond == 0))
  762. {
  763. // Either the timer doesn't work, or we're doing a 'test render':
  764. *seconds = 1000000.0f;
  765. *iterations = 1;
  766. }
  767. else
  768. {
  769. // Woo hoo, we're done!
  770. *seconds = static_cast<float>(counter - StartCounter) / CountsPerSecond;
  771. *iterations = Iterations;
  772. }
  773. }