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