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