home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / directx2 / sdk / samples / memtime / memtime.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-28  |  30.6 KB  |  947 lines

  1. //--------------------------------------------------------------------------;
  2. //
  3. //  File: memtime.cpp
  4. //
  5. //  Description:
  6. //      This code times various things about system memory and video
  7. //      memory. It is intended to show the advantages and disadvantages
  8. //      of different drawing methoids.
  9. //      Please refer to the documented for a more detailed discriptions of
  10. //      what is going on.
  11. //
  12. //
  13. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  14. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  15. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  16. //  PURPOSE.
  17. //
  18. //---------------------------------------------------------------------------
  19. //
  20. //  Copyright (c) 1994 - 1996 Microsoft Corporation.  All Rights Reserved.
  21. //
  22. //---------------------------------------------------------------------------
  23.  
  24. #include<windows.h>
  25. #include<windowsx.h>
  26. #include<commdlg.h>
  27. #include<strstrea.h>
  28. #include<iomanip.h>
  29. #include <ddraw.h>
  30.  
  31. #include"memtime.h"
  32.  
  33. /*----------------------------------------------------------------------------*\
  34. |                                                                                                                                                          |
  35. |   g l o b a l   v a r i a b l e s                                                                                    |
  36. |                                                                                                                                                          |
  37. \*----------------------------------------------------------------------------*/
  38. static  char    szAppName[]="Direct Draw video/system memory timing tests";
  39.  
  40. static HINSTANCE    hInstApp;
  41. static HWND         hwndApp;
  42. static HACCEL       hAccelApp;
  43. static HPALETTE     hpalApp;
  44.  
  45. static DWORD ScreenHeight, ScreenWidth;
  46. static PCHAR pSource, pDest;
  47.  
  48. static LPDIRECTDRAW pDirectDrawObj;
  49. static LPDIRECTDRAWSURFACE pOnScreenBuf;
  50. static LPDIRECTDRAWSURFACE pOffScreenBuf;
  51. static LPDIRECTDRAWSURFACE pSysMemBuf;
  52.  
  53. static ULONG ModeXFrameCount;
  54. static ULONG ModeYFrameCount;
  55. static ULONG StretchFrameCount;
  56.  
  57. /*----------------------------------------------------------------------------
  58.  
  59. Timers
  60.  
  61. */
  62.  
  63. extern "C" MemFunc DwordMemCopy_Pitch;
  64. extern "C" MemFunc ByteMemCopy_Pitch;
  65.  
  66. extern "C" MemFunc DwordMemFill_Pitch;
  67. extern "C" MemFunc ByteMemFill_Pitch;
  68.  
  69. extern "C" MemFunc VertMemSto_Pitch;
  70.  
  71.  
  72. TIMING_RESULT SystemTests[]=
  73. {
  74.     {0, DwordMemCopy_Pitch, "System to System dword copy"},
  75.     {0, ByteMemCopy_Pitch, "System to System byte copy"},
  76.  
  77.     {0, DwordMemFill_Pitch, "System dword Fill"},
  78.     {0, ByteMemFill_Pitch, "System byte Fill"},
  79.  
  80.     {0, VertMemSto_Pitch, "System vertical byte fill"}
  81. };
  82.  
  83.  
  84. TIMING_RESULT VideoTests[]=
  85. {
  86.     {0, DwordMemCopy_Pitch, "System to Video dword Copy"},
  87.     {0, ByteMemCopy_Pitch, "System to Video byte Copy"},
  88.  
  89.     {0, DwordMemFill_Pitch, "Video dword Fill"},
  90.     {0, ByteMemFill_Pitch, "Video byte Fill"},
  91.  
  92.     {0, VertMemSto_Pitch, "Video vertical byte fill"}
  93. };
  94.  
  95.  
  96.  
  97.  
  98. /*----------------------------------------------------------------------------
  99.  
  100. defines
  101.  
  102. */
  103.  
  104. #define NUMBER_OF(aa) (sizeof(aa)/sizeof((aa)[0]))
  105.         
  106.  
  107. /*----------------------------------------------------------------------------*\
  108. |
  109. |   f u n c t i o n   d e f i n i t i o n s
  110. |
  111. \*----------------------------------------------------------------------------*/
  112.  
  113. LRESULT CALLBACK AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
  114. int  ErrMsg (LPSTR sz,...);
  115. LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
  116. void PrintTimingResults( void );
  117.  
  118. void AppExit(void);
  119. BOOL AppIdle(void);
  120. BOOL DirectDrawInit();
  121. VOID DoSystemTest( PTIMING_RESULT pTimeObject );
  122. VOID DoVideoTests( PTIMING_RESULT pTimeObject );
  123. ULONG GetFPS( int width, int height );
  124. ULONG GetStretchFPS( int width, int height );
  125.  
  126. /*----------------------------------------------------------------------------*\
  127. |   AppAbout( hDlg, uiMessage, wParam, lParam )                             
  128. |
  129. |   Description:                                                            
  130. |       This function handles messages belonging to the "About" dialog box.
  131. |       The only message that it looks for is WM_COMMAND, indicating the use
  132. |       has pressed the "OK" button.  When this happens, it takes down
  133. |       the dialog box.                                               
  134. |                                                                             
  135. |   Arguments:                                                            
  136. |       hDlg        window handle of about dialog window  
  137. |       uiMessage   message number                        
  138. |       wParam      message-dependent                     
  139. |       lParam      message-dependent                     
  140. |                                                                             
  141. |   Returns:                                                              
  142. |       TRUE if message has been processed, else FALSE                
  143. |                                                                             
  144. \*----------------------------------------------------------------------------*/
  145. BOOL CALLBACK
  146. AppAbout( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
  147. {
  148.     switch (msg) {
  149.         case WM_COMMAND:
  150.             if (LOWORD(wParam) == IDOK) {
  151.                 EndDialog(hwnd,TRUE);
  152.             }
  153.             break;
  154.         case WM_INITDIALOG:
  155.             return TRUE;
  156.     }
  157.     return FALSE;
  158. }
  159.  
  160. /*----------------------------------------------------------------------------*\
  161. |   AppInit( hInst, hPrev)                                                  
  162. |
  163. |   Description:                                                            
  164. |       This is called when the application is first loaded into        
  165. |       memory.  It performs all initialization that doesn't need to be done
  166. |       once per instance.                                              
  167. |                                                                               
  168. |   Arguments:                                                              
  169. |       hInstance               instance handle of current instance     
  170. |       hPrev                   instance handle of previous instance    
  171. |                                                                               
  172. |   Returns:                                                                
  173. |       TRUE if successful, FALSE if not                                
  174. |                                                                               
  175. \*----------------------------------------------------------------------------*/
  176. BOOL
  177. AppInit(HINSTANCE hInst, HINSTANCE hPrev, int sw, LPSTR szCmdLine )
  178. {
  179.     WNDCLASS cls;
  180.     HRESULT ddrval;
  181.     DDSURFACEDESC ddsd;
  182.     BOOL returnValue = FALSE;
  183.     
  184.     /* Save instance handle for DialogBoxs */
  185.     hInstApp = hInst;
  186.     
  187.     hAccelApp = LoadAccelerators(hInst, "AppAccel");
  188.     
  189.     if (!hPrev) {
  190.         /*
  191.          *      Register a class for the main application window
  192.          */
  193.         cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  194.         cls.hIcon                  = LoadIcon(hInst,"AppIcon");
  195.         cls.lpszMenuName   = "AppMenu";
  196.         cls.lpszClassName  = szAppName;
  197.         cls.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  198.         cls.hInstance      = hInst;
  199.         cls.style                  = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  200.         cls.lpfnWndProc    = (WNDPROC)AppWndProc;
  201.         cls.cbWndExtra     = 0;
  202.         cls.cbClsExtra     = 0;
  203.         
  204.         if (RegisterClass(&cls)) {
  205.             hwndApp = CreateWindow (
  206.                         szAppName,      // Class name
  207.                         szAppName,      // Caption
  208.                         WS_OVERLAPPEDWINDOW,        // Style bits
  209.                         50, 50,         // Position
  210.                         400+20,400+75,  // Size
  211.                         (HWND)NULL,     // Parent window (no parent)
  212.                         (HMENU)NULL,    // use class menu
  213.                         hInst,          // handle to window instance
  214.                         (LPSTR)NULL);   // no params to pass on
  215.             ShowWindow(hwndApp,sw);
  216.  
  217.             // init our direct draw stuff
  218.             ddrval = DirectDrawCreate( NULL, &pDirectDrawObj, NULL );
  219.             if( DD_OK == ddrval) {
  220.                 // clear out the surface desctiptions
  221.                 ZeroMemory( &ddsd, sizeof( ddsd ) );
  222.                 // set the size
  223.                 ddsd.dwSize = sizeof( ddsd );
  224.  
  225.                 // figure out what display mode we are in now
  226.                 ddrval = pDirectDrawObj->GetDisplayMode( &ddsd );
  227.                 if( DD_OK == ddrval ) {
  228.                     // make sure we're in  a 8-bit mode
  229.                     if( ddsd.ddpfPixelFormat.dwRGBBitCount >= 8) {
  230.                         ScreenHeight = ddsd.dwHeight;
  231.                         ScreenWidth = ddsd.dwWidth;
  232.         
  233.                         // if we are biger than 800x600 it's to much memory
  234.                         // to move around. Clip it
  235.                         if(ScreenHeight > 600) ScreenHeight = 600;
  236.                         if(ScreenWidth > 800) ScreenWidth = 800;
  237.  
  238.                         if( (ScreenWidth < 800) || (ScreenHeight < 600) ) {
  239.                             ErrMsg("Resolutions smaller than 800x600 may yeild different numbers because of L2 cache effects");
  240.                         }
  241.                         
  242.                         // allocate some memory we are going to play with
  243.                         pSource = (PCHAR)GlobalAllocPtr(GHND, ScreenHeight * ScreenWidth);
  244.                         pDest = (PCHAR)GlobalAllocPtr(GHND, ScreenHeight * ScreenWidth);
  245.  
  246.                         // make sure the memory worked and it's dword alligned.
  247.                         // (we're in Win32, when is not going to be dword alligned?)
  248.                         if( pSource && pDest && !((DWORD)pSource & 0x3) && !((DWORD)pDest & 0x3)) {
  249.                             returnValue = TRUE;
  250.                         } else {
  251.                             ErrMsg("Memory allocation failure");
  252.                         }
  253.                     } else {
  254.                         ErrMsg("You must be in a 8-bit (or better) color mode to run this app");
  255.                     }
  256.                 } else {
  257.                     ErrMsg("DirectDraw failure getting the display mode");
  258.                 }
  259.             } else {
  260.                 ErrMsg("DirectDraw create failure");
  261.             }
  262.         } else {
  263.             ErrMsg("Register Class failure");
  264.         }
  265.     }
  266.     return returnValue;
  267. }
  268.  
  269. /*----------------------------------------------------------------------------*\
  270. |   BandwidthTestsSetup
  271. |
  272. |   Description:
  273. |       Setup the surfaces for the bandwidth tests
  274. |
  275. |   Returns:                                                                
  276. |       TRUE if successful, FALSE if not                                
  277. \*----------------------------------------------------------------------------*/
  278. BOOL
  279. BandwidthTestsSetup( VOID )
  280. {
  281.     DDSURFACEDESC ddsd;
  282.     BOOL returnValue = FALSE;
  283.     HRESULT ddrval;
  284.  
  285.     if( pOnScreenBuf ) pOnScreenBuf->Release();
  286.     if( pOffScreenBuf ) pOffScreenBuf->Release();
  287.     if( pSysMemBuf ) pSysMemBuf->Release();
  288.     
  289.     // Tell the world we love it and want to share
  290.     ddrval = pDirectDrawObj->SetCooperativeLevel( hwndApp, DDSCL_NORMAL );
  291.     if( DD_OK == ddrval ) {
  292.         // clear out out stuff
  293.         ZeroMemory( &ddsd, sizeof( ddsd ) );
  294.         ddsd.dwSize = sizeof( ddsd );
  295.  
  296.         ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  297.         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  298.  
  299.         ddsd.dwHeight = ScreenHeight;
  300.         ddsd.dwWidth = ScreenWidth;
  301.         // create our off screen video memory.
  302.         ddrval = pDirectDrawObj->CreateSurface( &ddsd, &pOffScreenBuf, NULL );
  303.         if( DD_OK == ddrval ) {
  304.             // yay!
  305.             returnValue = TRUE;
  306.         } else {
  307.             ErrMsg("Failure creating video surface");
  308.         }
  309.     } else {
  310.         ErrMsg("Failure setting Co-op mode");
  311.     }
  312.     return returnValue;
  313. }
  314. /*----------------------------------------------------------------------------*\
  315. |   AppExit()
  316. |
  317. |   Description:
  318. |       app is just about to exit, cleanup
  319. |
  320. \*----------------------------------------------------------------------------*/
  321. void AppExit()
  322. {
  323.     if( pSource ) GlobalFreePtr(pSource);
  324.     if( pDest ) GlobalFreePtr(pDest);
  325.     if( pOffScreenBuf ) pOffScreenBuf->Release();
  326.     if( pOnScreenBuf ) pOnScreenBuf->Release();
  327.     if( pSysMemBuf ) pSysMemBuf->Release();
  328.     if( pDirectDrawObj ) pDirectDrawObj->Release();
  329.  
  330. }
  331.  
  332. /*----------------------------------------------------------------------------*\
  333. |   WinMain( hInst, hPrev, lpszCmdLine, cmdShow )                                                      |
  334. |
  335. |   Description:
  336. |       The main procedure for the App.  After initializing, it just goes
  337. |       into a message-processing loop until it gets a WM_QUIT message
  338. |       (meaning the app was closed).                                                                              |
  339. |
  340. |   Arguments:
  341. |       hInst       instance handle of this instance of the app
  342. |       hPrev       instance handle of previous instance, NULL if first
  343. |       szCmdLine   ->null-terminated command line
  344. |       cmdShow     specifies how the window is initially displayed
  345. |
  346. |       Returns:
  347. |               The exit code as specified in the WM_QUIT message.
  348. |
  349. \*----------------------------------------------------------------------------*/
  350. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
  351. {
  352.     MSG msg;
  353.  
  354.     /* Call initialization procedure */
  355.     if (!AppInit(hInst,hPrev,sw,szCmdLine))
  356.     return FALSE;
  357.  
  358.     /*
  359.      * Polling messages from event queue
  360.      */
  361.     for (;;) {
  362.         if(!GetMessage(&msg, NULL, 0, 0)) {
  363.             return msg.wParam;
  364.         }
  365.         TranslateMessage(&msg);
  366.         DispatchMessage(&msg);
  367.     }
  368.  
  369.     return msg.wParam;
  370. }
  371.  
  372.  
  373. /*----------------------------------------------------------------------------*\
  374. |   AppPaint(hwnd, hdc)
  375. |
  376. |   Description:
  377. |       The paint function.  Right now this does nothing.
  378. |
  379. |   Arguments:
  380. |       hwnd    window painting into
  381. |       hdc     display context to paint to
  382. |
  383. |   Returns:
  384. |       nothing
  385. |
  386. \*----------------------------------------------------------------------------*/
  387. AppPaint (HWND hwnd, HDC hdc)
  388. {
  389.     TEXTMETRIC tm;
  390.     int     x,y;
  391.     RECT    rc;
  392.     
  393. #define PRINT_STUFF(sz) (TextOut(hdc, x, y, sz, lstrlen(sz)), y += tm.tmHeight+1)
  394.  
  395.     SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));
  396.     GetTextMetrics(hdc, &tm);
  397.  
  398.     GetClientRect(hwnd,&rc);
  399.     
  400.     SetTextColor(hdc,GetSysColor(COLOR_WINDOWTEXT));
  401.     SetBkColor(hdc,GetSysColor(COLOR_WINDOW));
  402.  
  403.     // setup start pos
  404.     x=4;
  405.     y=4;
  406.  
  407.     PRINT_STUFF("Select 'Time All' to run tests");
  408.     y += (tm.tmHeight+1) * 2;
  409.     PRINT_STUFF("The screen will go blank during some tests");
  410.  
  411.     return TRUE;
  412. }
  413.  
  414. /*----------------------------------------------------------------------------*\
  415. |   AppWndProc( hwnd, uiMessage, wParam, lParam )
  416. |
  417. |   Description:
  418. |       The window proc for the app's main (tiled) window.
  419. |       This processes all of the parent window's messages.
  420. |
  421. \*----------------------------------------------------------------------------*/
  422. LRESULT CALLBACK AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  423. {
  424.     PAINTSTRUCT ps;
  425.     HDC hdc;
  426.  
  427.     switch (msg) {
  428.         case WM_COMMAND:
  429.             return AppCommand(hwnd,msg,wParam,lParam);
  430.             break;
  431.  
  432.         case WM_PAINT:
  433.             hdc = BeginPaint(hwnd,&ps);
  434.             AppPaint( hwnd, hdc );
  435.             break;
  436.  
  437.         case WM_DESTROY:
  438.             hAccelApp = NULL;
  439.             PostQuitMessage(0);
  440.             break;
  441.  
  442.     }
  443.     return DefWindowProc(hwnd,msg,wParam,lParam);
  444. }
  445.  
  446. /*----------------------------------------------------------------------------*\
  447. |   AppCommand(hwnd, msg, wParam, lParam )
  448. |
  449. |   Description:
  450. |       handles WM_COMMAND messages for the main window (hwndApp)
  451. |       of the parent window's messages.
  452. |
  453. \*----------------------------------------------------------------------------*/
  454. LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  455. {
  456.     char achFileName[128] = "";
  457.     
  458.     switch(wParam) {
  459.         case MENU_ABOUT:
  460.             DialogBox(hInstApp,"AppAbout",hwnd,(DLGPROC)AppAbout);
  461.             break;
  462.         
  463.  
  464.         // do all the timing tests
  465.         case MENU_TIMEALL:
  466.             {
  467.             HCURSOR Arror = SetCursor(LoadCursor(0,IDC_WAIT));
  468.  
  469.             DWORD PriorityClass = GetPriorityClass(GetCurrentProcess());
  470.             int ThreadPriority = GetThreadPriority(GetCurrentThread());
  471.  
  472.             if( NUMBER_OF(SystemTests) != NUMBER_OF(VideoTests))
  473.             {
  474.                 ErrMsg("test number mismatch");
  475.                 break;
  476.             }
  477.  
  478.             // Jack this thread up to realtime.
  479.             // NOTE: This is very bad from for the real world. The rule is
  480.             // "The Higher your ptiority, the less work your thread should do".
  481.             // We are doing a lot of work. But this is only a test app, so who cares.
  482.             SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
  483.             SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
  484.  
  485.             // setup the surfaces for the bandwidth tests
  486.             BandwidthTestsSetup();
  487.             // Walk through the list of timers, and call them all
  488.  
  489.             for(int Counter = 0;Counter < NUMBER_OF(SystemTests) ;Counter++) {
  490.  
  491.                 SetWindowText(hwndApp,SystemTests[Counter].pDescription);
  492.  
  493.                 DoSystemTest( &SystemTests[Counter] );
  494.  
  495.                 SetWindowText(hwndApp,VideoTests[Counter].pDescription);
  496.  
  497.                 DoVideoTests( &VideoTests[Counter] );
  498.             
  499.             }
  500.  
  501.             // do 320x240 frame rate tests
  502.             ModeXFrameCount = GetFPS(320,240);
  503.             // do 640x480 frame rate tests
  504.             ModeYFrameCount = GetFPS(640,480);
  505.             // do 320x240 stretch to 640x480 frame rate tests
  506.             StretchFrameCount = GetStretchFPS(640,480);
  507.  
  508.             // return ourselves to normal
  509.             SetPriorityClass(GetCurrentProcess(),PriorityClass);
  510.             SetThreadPriority(GetCurrentThread(),ThreadPriority);
  511.  
  512.             SetCursor(Arror);
  513.             SetWindowText(hwndApp,szAppName);
  514.             
  515.             PrintTimingResults();
  516.             }
  517.             break;
  518.  
  519.         case MENU_EXIT:
  520.             PostMessage(hwnd,WM_CLOSE,0,0L);
  521.             break;
  522.     }
  523.     return 0L;
  524. }
  525.  
  526. /*----------------------------------------------------------------------------*\
  527. |   ErrMsg - Opens a Message box with a error message in it.  The user can
  528. |       select the OK button to continue
  529. \*----------------------------------------------------------------------------*/
  530. int ErrMsg (LPSTR sz,...)
  531. {
  532.         char ach[128];
  533.  
  534.         wvsprintf (ach,sz,(LPSTR)(&sz+1));       /* Format the string */
  535.         MessageBox(hwndApp,ach,szAppName,MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL);
  536.         return FALSE;
  537. }
  538.  
  539.  
  540.  
  541.  
  542. /*----------------------------------------------------------------------------*\
  543. |   PrintTimingResults( void )
  544. |
  545. |   Description:
  546. |       Print the results of the timting tests
  547. |
  548. \*----------------------------------------------------------------------------*/
  549. VOID
  550. PrintTimingResults( void )
  551. {
  552.     double result;
  553.     LARGE_INTEGER perfFreq;
  554.     char OutputBuffer[2048];
  555.  
  556.     ostrstream Out(OutputBuffer,sizeof(OutputBuffer));
  557.  
  558.  
  559.     // get the frequemcy out of timer
  560.     QueryPerformanceFrequency( &perfFreq );
  561.  
  562.     // Turn all the time resutls into MB per second
  563.     for(int Counter = 0; Counter < NUMBER_OF(SystemTests) ; Counter++) {
  564.         if(SystemTests[Counter].Time) {
  565.             result = (double)SystemTests[Counter].Iterations;
  566.             result /= (double)SystemTests[Counter].Time / (double)perfFreq.LowPart;
  567.             result /= (double)1000000.0;
  568.             Out<<result;
  569.         } else {
  570.             Out<<"N/A";
  571.         }
  572.         Out<<" MB/sec \t";
  573.         Out<<SystemTests[Counter].pDescription<<endl;
  574.  
  575.         if(VideoTests[Counter].Time) {
  576.             result = (double)VideoTests[Counter].Iterations;
  577.             result /= (double)VideoTests[Counter].Time / (double)perfFreq.LowPart;
  578.             result /= (double)1000000.0;
  579.             Out<<result;            
  580.         } else {
  581.             Out<<"N/A";
  582.         }
  583.         Out<<" MB/sec \t";
  584.         Out<<VideoTests[Counter].pDescription<<endl;
  585.  
  586.  
  587.     }
  588.  
  589.     if( ModeXFrameCount ) {
  590.         Out<<((double)ModeXFrameCount/5.0);
  591.     } else {
  592.         Out<<"N/A";
  593.     }
  594.     Out<<" FPS \t\t";
  595.     Out<<"320x240 Frame Rate"<<endl;
  596.  
  597.     if( ModeYFrameCount ) {
  598.         Out<<((double)ModeYFrameCount/5.0);
  599.     } else {
  600.         Out<<"N/A";
  601.     }
  602.     Out<<" FPS \t\t";
  603.     Out<<"640x480 Frame Rate"<<endl;
  604.  
  605.     if( StretchFrameCount ) {
  606.         Out<<((double)StretchFrameCount/5.0);
  607.     } else {
  608.         Out<<"N/A";
  609.     }
  610.     Out<<" FPS \t\t";
  611.     Out<<"320x240 stretched to 640x480"<<endl;
  612.  
  613.     Out<<ends;
  614. #ifndef LOR_TESTS
  615.     // display the results
  616.     MessageBox(0, OutputBuffer ,"Timing Results",MB_OK);
  617. #endif
  618.  
  619. }
  620.  
  621. VOID DoSystemTest( PTIMING_RESULT pTimeObject )
  622. {
  623.     LARGE_INTEGER startTime, endTime;
  624.  
  625.     QueryPerformanceCounter( &startTime );
  626.  
  627.     // do the memory copy
  628.     pTimeObject->Iterations = (*pTimeObject->pTimer)(pSource, pDest, ScreenHeight, ScreenWidth, ScreenWidth, 100 );
  629.     
  630.     QueryPerformanceCounter( &endTime );
  631.  
  632.     // if it takes more than 32bits of clock ticks
  633.     // it's not worth profiling.
  634.     pTimeObject->Time = endTime.LowPart - startTime.LowPart;
  635. }
  636.  
  637. VOID DoVideoTests( PTIMING_RESULT pTimeObject )
  638. {
  639.     DDSURFACEDESC ddsd;
  640.     HRESULT returnValue;
  641.     LARGE_INTEGER startTime, endTime;
  642.  
  643.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  644.     ddsd.dwSize = sizeof( ddsd );
  645.  
  646.  
  647.     // lock the video memory surfce
  648.     // NOTE: We are about to do a lock for a REALLY long time.
  649.     // this is really bad form in the real world.
  650.     //
  651.     returnValue = pOffScreenBuf->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL);
  652.     if( returnValue == DD_OK )
  653.     {
  654.         if( ddsd.lPitch && ddsd.dwWidth && ddsd.dwHeight && ddsd.lpSurface)
  655.         {
  656.             // get the time, and do the copy
  657.             QueryPerformanceCounter( &startTime );
  658.  
  659.             pTimeObject->Iterations = (*pTimeObject->pTimer)( pSource, ddsd.lpSurface, ddsd.dwHeight, ddsd.dwWidth, ddsd.lPitch, 100 );
  660.  
  661.             QueryPerformanceCounter( &endTime );
  662.  
  663.             pOffScreenBuf->Unlock( ddsd.lpSurface );
  664.             // stor the delta time
  665.             pTimeObject->Time = endTime.LowPart - startTime.LowPart;
  666.         }
  667.         else
  668.         {
  669.             pOffScreenBuf->Unlock( ddsd.lpSurface );
  670.             ErrMsg("Lock returned bogus Session Description stuff");
  671.         }
  672.     }
  673.     else
  674.         ErrMsg("Can't lock surface");
  675.  
  676.     return;
  677. }
  678.  
  679. BOOL
  680. InitFullScreen(
  681.     DWORD Height,
  682.     DWORD Width
  683.     )
  684. {
  685.     DDSURFACEDESC ddsd;
  686.     DDSCAPS ddscaps;
  687.     HRESULT ddrval;
  688.     ULONG returnValue = FALSE;
  689.  
  690.     // Kill our current offscreen surface.
  691.     if( pOffScreenBuf ) {
  692.         ddrval = pOffScreenBuf->Release();
  693.         if( ddrval != DD_OK ) {
  694.             ErrMsg("Can't release offscreen buf");
  695.         }
  696.     }
  697.  
  698.  
  699.     // Get exclusive mode
  700.     ddrval = pDirectDrawObj->SetCooperativeLevel( hwndApp, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_NOWINDOWCHANGES );
  701.  
  702.     if( ddrval == DD_OK ){
  703.         // set the display mode to the requested mode
  704.         ddrval = pDirectDrawObj->SetDisplayMode( Height, Width, 8);
  705.         if(ddrval == DD_OK){
  706.             ddsd.dwSize = sizeof( ddsd );
  707.             ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  708.             ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
  709.                           DDSCAPS_FLIP |
  710.                           DDSCAPS_COMPLEX;
  711.             ddsd.dwBackBufferCount = 1;
  712.             // get the primary buffer
  713.             ddrval = pDirectDrawObj->CreateSurface( &ddsd, &pOnScreenBuf, NULL );
  714.  
  715.             if( ddrval == DD_OK ) {
  716.                 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  717.                 // the back buffer might be in system memory depending
  718.                 // on the card and the mode.
  719.                 ddrval = pOnScreenBuf->GetAttachedSurface(&ddscaps, &pOffScreenBuf);
  720.  
  721.                 if( ddrval == DD_OK ) {
  722.                     returnValue = TRUE;
  723.                 } 
  724.             }
  725.         } else {
  726.             ErrMsg("can't set display mode %d x %d",Width,Height);
  727.         }
  728.     }
  729.     return returnValue;
  730. }
  731.  
  732.  
  733. BOOL
  734. CreateSysMemSurface( VOID )
  735. {
  736.     DDSURFACEDESC ddsd;
  737.     ULONG returnValue;
  738.  
  739.     // clear out out stuff
  740.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  741.     ddsd.dwSize = sizeof( ddsd );
  742.  
  743.     // build a surface in system memory
  744.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  745.     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
  746.     
  747.     ddsd.dwHeight = 240;
  748.     ddsd.dwWidth = 320;
  749.     returnValue = pDirectDrawObj->CreateSurface( &ddsd, &pSysMemBuf, NULL );
  750.     if( DD_OK == returnValue ) {
  751.         return TRUE;
  752.     }
  753.  
  754.     return FALSE;
  755. }
  756.  
  757. ULONG
  758. GetStretchFPS( int width, int height )
  759. {
  760.     ULONG time;
  761.     HRESULT ddrval;
  762.     DDSURFACEDESC ddsd;
  763.     DDBLTFX     ddbltfx;
  764.     ULONG FrameCount;
  765.  
  766.     // set the mode (and create the surfaces)
  767.     if( InitFullScreen( width, height ) ) {
  768.         // get the system memory surface
  769.         if( CreateSysMemSurface() ) {
  770.  
  771.             // build the ROP for the blt
  772.             ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
  773.             ddbltfx.dwSize = sizeof( ddbltfx );
  774.             ddbltfx.dwROP = SRCCOPY;
  775.  
  776.             time = timeGetTime();
  777.             // wait for a seconds for the mode to settle out
  778.             // (I don't need to do this.. I'm just paranoid)
  779.             while( (timeGetTime() - time) < 1000);
  780.             FrameCount = 0;
  781.             time = timeGetTime();
  782.  
  783.             // Initialize the surface description structure
  784.             ZeroMemory(&ddsd, sizeof(ddsd));
  785.             ddsd.dwSize=sizeof(ddsd);
  786.  
  787.             ddrval = 0;
  788.             // do this for 5 seconds
  789.             while( ((timeGetTime() - time) < 5000) && (DD_OK == ddrval) ) {
  790.                 // simluate rendering and off screen frame (with a copy)
  791.                 ddrval = pSysMemBuf->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
  792.                 if (FAILED(ddrval))
  793.                 {
  794.                     FrameCount=0;
  795.                     break;
  796.                 }
  797.  
  798.                 DwordMemCopy_Pitch( pSource, ddsd.lpSurface, ddsd.dwHeight, ddsd.dwWidth, ddsd.lPitch, 1);
  799.  
  800.                 ddrval = pSysMemBuf->Unlock( NULL );
  801.                 if (FAILED(ddrval))
  802.                 {
  803.                     FrameCount=0;
  804.                     break;
  805.                 }
  806.  
  807.                 // blt the system buffer into the back buffer
  808.                 ddrval = pOffScreenBuf->Blt( NULL, pSysMemBuf, NULL, DDBLT_ROP, &ddbltfx);
  809.                 if (FAILED(ddrval))
  810.                 {
  811.                     FrameCount=0;
  812.                     break;
  813.                 }
  814.  
  815.                 // flip the back buffer on screen
  816.                 ddrval = pOnScreenBuf->Flip( NULL, DDFLIP_WAIT );
  817.                 if (FAILED(ddrval))
  818.                 {
  819.                     FrameCount=0;
  820.                     break;
  821.                 }
  822.  
  823.                 FrameCount++;
  824.             }
  825.         }
  826.         pDirectDrawObj->RestoreDisplayMode();
  827.         if( DD_OK != ddrval ) {
  828.             ErrMsg("Test failure %X",ddrval);
  829.         }
  830.  
  831.         pOffScreenBuf->Release();
  832.         pOffScreenBuf = NULL;
  833.         pOnScreenBuf->Release();
  834.         pOnScreenBuf = NULL;
  835.         pSysMemBuf->Release();
  836.         pSysMemBuf = NULL;
  837.     }
  838.     return FrameCount;
  839. }
  840.  
  841. ULONG GetFPS( int width, int height )
  842. {
  843.     ULONG time;
  844.     DDSURFACEDESC ddsd;
  845.     HRESULT ddrval;
  846.     ULONG FrameCount;
  847.  
  848.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  849.     ddsd.dwSize = sizeof( ddsd );
  850.  
  851.     // set the mode (and setup the surfaces)    
  852.     if( InitFullScreen( width, height ) )
  853.     {
  854.         time = timeGetTime();
  855.         // wait for a seconds for the mode to settle out
  856.         // (I don't need to do this, I'm just paranoid)
  857.         while( (timeGetTime() - time) < 1000);
  858.         ddrval = DD_OK;
  859.         FrameCount = 0;
  860.         time = timeGetTime();
  861.         while( ((timeGetTime() - time) < 5000) && (ddrval == DD_OK) )
  862.         {
  863.             // simluate a render into the back buffer with a copy
  864.             ddrval = pOffScreenBuf->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
  865.             if (FAILED(ddrval))
  866.             {
  867.                 FrameCount=0;
  868.                 break;
  869.             }
  870.             // Stuff some Junk into the offscreen surface
  871.             DwordMemCopy_Pitch( pSource, ddsd.lpSurface, ddsd.dwHeight, ddsd.dwWidth, ddsd.lPitch, 1 );
  872.  
  873.             ddrval = pOffScreenBuf->Unlock( NULL );
  874.             if (FAILED(ddrval))
  875.             {
  876.                 FrameCount=0;
  877.                 break;
  878.             }
  879.  
  880.             // flip the off screen surface on screen
  881.             ddrval = pOnScreenBuf->Flip( NULL, DDFLIP_WAIT );
  882.             if (FAILED(ddrval))
  883.             {
  884.                 FrameCount=0;
  885.                 break;
  886.             }
  887.  
  888.             FrameCount++;
  889.         }
  890.         pDirectDrawObj->RestoreDisplayMode();
  891.         if( FAILED(ddrval) )
  892.             ErrMsg("Test failure %X",ddrval);
  893.         pOffScreenBuf->Release();
  894.         pOffScreenBuf = NULL;
  895.         pOnScreenBuf->Release();
  896.         pOnScreenBuf = NULL;
  897.     }
  898.  
  899.     return FrameCount;
  900. }
  901.  
  902. /*****************************************************************************
  903.  *
  904.  * dprintf() is called by the DPF macro if DEBUG is defined at compile time.
  905.  *
  906.  * The messages will be send to COM1: like any debug message. To
  907.  * enable debug output, add the following to WIN.INI :
  908.  *
  909.  * [debug]
  910.  * QA=1
  911.  *
  912.  ****************************************************************************/
  913.  
  914. #ifdef DEBUG
  915.  
  916. #define MODNAME "QA"
  917.  
  918.  
  919. #define _WINDLL
  920. #include <stdarg.h>
  921.  
  922. void FAR CDECL dprintf(LPSTR szFormat, ...)
  923. {
  924.     char ach[128];
  925.     va_list va;
  926.     
  927.     static BOOL fDebug = -1;
  928.     
  929.     if (fDebug == -1) {
  930.         fDebug = GetProfileIntA("Debug", MODNAME, TRUE);
  931.     }
  932.     
  933.     if (!fDebug) return;
  934.  
  935.     
  936.     
  937.     lstrcpyA(ach, MODNAME ": ");
  938.     va_start(va, szFormat);
  939.     wvsprintfA(ach+lstrlenA(ach),szFormat,(LPSTR)va);
  940.     va_end(va);
  941.     lstrcatA(ach, "\r\n");
  942.     
  943.     OutputDebugStringA(ach);
  944. }
  945.  
  946. #endif
  947.