home *** CD-ROM | disk | FTP | other *** search
/ Microsoft DirectX SDK 6.1 / Dx6_1_Gold.iso / dxf / samples / multimedia / ddraw / src / memtime / memtime.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-11-30  |  31.3 KB  |  962 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 methods.
  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 - 1997 Microsoft Corporation.  All Rights Reserved.
  21. //
  22. //---------------------------------------------------------------------------
  23.  
  24. #include <windows.h>
  25. #include <winnt.h>
  26. #include <windowsx.h>
  27. #include <commdlg.h>
  28. #include <ddraw.h>
  29. #include <mmsystem.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.             ShowCursor(FALSE);  //take care of animated Plus! cursors
  470.  
  471.             DWORD PriorityClass = GetPriorityClass(GetCurrentProcess());
  472.             int ThreadPriority = GetThreadPriority(GetCurrentThread());
  473.  
  474.             if( NUMBER_OF(SystemTests) != NUMBER_OF(VideoTests))
  475.             {
  476.                 ErrMsg("test number mismatch");
  477.                 break;
  478.             }
  479.  
  480.             // Jack this thread up to realtime.
  481.             // NOTE: This is very bad from for the real world. The rule is
  482.             // "The Higher your ptiority, the less work your thread should do".
  483.             // We are doing a lot of work. But this is only a test app, so who cares.
  484.             SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
  485.             SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
  486.  
  487.             // setup the surfaces for the bandwidth tests
  488.             BandwidthTestsSetup();
  489.             // Walk through the list of timers, and call them all
  490.  
  491.             for(int Counter = 0;Counter < NUMBER_OF(SystemTests) ;Counter++) {
  492.  
  493.                 SetWindowText(hwndApp,SystemTests[Counter].pDescription);
  494.  
  495.                 DoSystemTest( &SystemTests[Counter] );
  496.  
  497.                 SetWindowText(hwndApp,VideoTests[Counter].pDescription);
  498.  
  499.                 DoVideoTests( &VideoTests[Counter] );
  500.             
  501.             }
  502.  
  503.             // do 320x240 frame rate tests
  504.             ModeXFrameCount = GetFPS(320,240);
  505.             // do 640x480 frame rate tests
  506.             ModeYFrameCount = GetFPS(640,480);
  507.             // do 320x240 stretch to 640x480 frame rate tests
  508.             StretchFrameCount = GetStretchFPS(640,480);
  509.  
  510.             // return ourselves to normal
  511.             SetPriorityClass(GetCurrentProcess(),PriorityClass);
  512.             SetThreadPriority(GetCurrentThread(),ThreadPriority);
  513.  
  514.             SetCursor(Arror);
  515.             SetWindowText(hwndApp,szAppName);
  516.             
  517.             ShowCursor(TRUE);
  518.             PrintTimingResults();
  519.             }
  520.             break;
  521.  
  522.         case MENU_EXIT:
  523.             PostMessage(hwnd,WM_CLOSE,0,0L);
  524.             break;
  525.     }
  526.     return 0L;
  527. }
  528.  
  529. /*----------------------------------------------------------------------------*\
  530. |   ErrMsg - Opens a Message box with a error message in it.  The user can
  531. |       select the OK button to continue
  532. \*----------------------------------------------------------------------------*/
  533. int ErrMsg (LPSTR sz,...)
  534. {
  535.         char ach[128];
  536.         va_list va;
  537.  
  538.         va_start( va, sz );
  539.         wvsprintf ( ach, sz, va );       /* Format the string */
  540.         va_end( va );
  541.         MessageBox(hwndApp,ach,szAppName,MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL);
  542.         return FALSE;
  543. }
  544.  
  545.  
  546.  
  547.  
  548. /*----------------------------------------------------------------------------*\
  549. |   PrintTimingResults( void )
  550. |
  551. |   Description:
  552. |       Print the results of the timting tests
  553. |
  554. \*----------------------------------------------------------------------------*/
  555. #include <stdio.h>
  556.  
  557. VOID
  558. PrintTimingResults( void )
  559. {
  560.     double result;
  561.     LARGE_INTEGER perfFreq;
  562.     char OutputBuffer[2048];
  563.     char TempOutputBuffer[2048];
  564. #define PRINT_DOUBLE(d) {sprintf(TempOutputBuffer,"%12.8f",d);strcat(OutputBuffer,TempOutputBuffer);}
  565. #define PRINT_STRING(s) {sprintf(TempOutputBuffer,"%s",s);strcat(OutputBuffer,TempOutputBuffer);}
  566.  
  567.     OutputBuffer[0]=0;
  568.     TempOutputBuffer[0]=0;
  569.  
  570.     // get the frequemcy out of timer
  571.     QueryPerformanceFrequency( &perfFreq );
  572.  
  573.     // Turn all the time resutls into MB per second
  574.     for(int Counter = 0; Counter < NUMBER_OF(SystemTests) ; Counter++) {
  575.         if(SystemTests[Counter].Time) {
  576.             result = (double)SystemTests[Counter].Iterations;
  577.             result /= (double)SystemTests[Counter].Time / (double)perfFreq.u.LowPart;
  578.             result /= (double)1000000.0;
  579.             PRINT_DOUBLE(result);
  580.         } else {
  581.             PRINT_STRING("N/A");
  582.         }
  583.         PRINT_STRING(" MB/sec \t");
  584.         PRINT_STRING(SystemTests[Counter].pDescription);
  585.         PRINT_STRING("\n");
  586.  
  587.         if(VideoTests[Counter].Time) {
  588.             result = (double)VideoTests[Counter].Iterations;
  589.             result /= (double)VideoTests[Counter].Time / (double)perfFreq.u.LowPart;
  590.             result /= (double)1000000.0;
  591.             PRINT_DOUBLE(result);
  592.         } else {
  593.             PRINT_STRING("N/A");
  594.         }
  595.         PRINT_STRING(" MB/sec \t");
  596.         PRINT_STRING(VideoTests[Counter].pDescription);
  597.         PRINT_STRING("\n");
  598.  
  599.     }
  600.  
  601.     if( ModeXFrameCount ) {
  602.         PRINT_DOUBLE((double)ModeXFrameCount/5.0);
  603.     } else {
  604.         PRINT_STRING("N/A");
  605.     }
  606.     PRINT_STRING(" FPS \t\t");
  607.     PRINT_STRING("320x240 Frame Rate");
  608.     PRINT_STRING("\n");
  609.  
  610.     if( ModeYFrameCount ) {
  611.         PRINT_DOUBLE((double)ModeYFrameCount/5.0);
  612.     } else {
  613.         PRINT_STRING("N/A");
  614.     }
  615.     PRINT_STRING(" FPS \t\t");
  616.     PRINT_STRING("640x480 Frame Rate");
  617.     PRINT_STRING("\n");
  618.  
  619.     if( StretchFrameCount ) {
  620.         PRINT_DOUBLE((double)StretchFrameCount/5.0);
  621.     } else {
  622.         PRINT_STRING("N/A");
  623.     }
  624.     PRINT_STRING(" FPS \t\t");
  625.     PRINT_STRING("320x240 stretched to 640x480");
  626.     PRINT_STRING("\n");
  627.  
  628. #ifndef LOR_TESTS
  629.     // display the results
  630.     MessageBox(0, OutputBuffer ,"Timing Results",MB_OK);
  631. #endif
  632.  
  633. }
  634.  
  635. VOID DoSystemTest( PTIMING_RESULT pTimeObject )
  636. {
  637.     LARGE_INTEGER startTime, endTime;
  638.  
  639.     QueryPerformanceCounter( &startTime );
  640.  
  641.     // do the memory copy
  642.     pTimeObject->Iterations = (*pTimeObject->pTimer)(pSource, pDest, ScreenHeight, ScreenWidth, ScreenWidth, 100 );
  643.     
  644.     QueryPerformanceCounter( &endTime );
  645.  
  646.     // if it takes more than 32bits of clock ticks
  647.     // it's not worth profiling.
  648.     pTimeObject->Time = endTime.u.LowPart - startTime.u.LowPart;
  649. }
  650.  
  651. VOID DoVideoTests( PTIMING_RESULT pTimeObject )
  652. {
  653.     DDSURFACEDESC ddsd;
  654.     HRESULT returnValue;
  655.     LARGE_INTEGER startTime, endTime;
  656.  
  657.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  658.     ddsd.dwSize = sizeof( ddsd );
  659.  
  660.  
  661.     // lock the video memory surfce
  662.     // NOTE: We are about to do a lock for a REALLY long time.
  663.     // this is really bad form in the real world.
  664.     //
  665.     returnValue = pOffScreenBuf->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL);
  666.     if( returnValue == DD_OK )
  667.     {
  668.         if( ddsd.lPitch && ddsd.dwWidth && ddsd.dwHeight && ddsd.lpSurface)
  669.         {
  670.             // get the time, and do the copy
  671.             QueryPerformanceCounter( &startTime );
  672.  
  673.             pTimeObject->Iterations = (*pTimeObject->pTimer)( pSource, ddsd.lpSurface, ddsd.dwHeight, ddsd.dwWidth, ddsd.lPitch, 100 );
  674.  
  675.             QueryPerformanceCounter( &endTime );
  676.  
  677.             pOffScreenBuf->Unlock( ddsd.lpSurface );
  678.             // stor the delta time
  679.             pTimeObject->Time = endTime.u.LowPart - startTime.u.LowPart;
  680.         }
  681.         else
  682.         {
  683.             pOffScreenBuf->Unlock( ddsd.lpSurface );
  684.             ErrMsg("Lock returned bogus Session Description stuff");
  685.         }
  686.     }
  687.     else
  688.         ErrMsg("Can't lock surface");
  689.  
  690.     return;
  691. }
  692.  
  693. BOOL
  694. InitFullScreen(
  695.     DWORD Height,
  696.     DWORD Width
  697.     )
  698. {
  699.     DDSURFACEDESC ddsd;
  700.     DDSCAPS ddscaps;
  701.     HRESULT ddrval;
  702.     ULONG returnValue = FALSE;
  703.  
  704.     // Kill our current offscreen surface.
  705.     if( pOffScreenBuf ) {
  706.         ddrval = pOffScreenBuf->Release();
  707.         if( ddrval != DD_OK ) {
  708.             ErrMsg("Can't release offscreen buf");
  709.         }
  710.     }
  711.  
  712.  
  713.     // Get exclusive mode
  714.     ddrval = pDirectDrawObj->SetCooperativeLevel( hwndApp, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_NOWINDOWCHANGES );
  715.  
  716.     if( ddrval == DD_OK ){
  717.         // set the display mode to the requested mode
  718.         ddrval = pDirectDrawObj->SetDisplayMode( Height, Width, 8);
  719.         if(ddrval == DD_OK){
  720.             ddsd.dwSize = sizeof( ddsd );
  721.             ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  722.             ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
  723.                           DDSCAPS_FLIP |
  724.                           DDSCAPS_COMPLEX;
  725.             ddsd.dwBackBufferCount = 1;
  726.             // get the primary buffer
  727.             ddrval = pDirectDrawObj->CreateSurface( &ddsd, &pOnScreenBuf, NULL );
  728.  
  729.             if( ddrval == DD_OK ) {
  730.                 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  731.                 // the back buffer might be in system memory depending
  732.                 // on the card and the mode.
  733.                 ddrval = pOnScreenBuf->GetAttachedSurface(&ddscaps, &pOffScreenBuf);
  734.  
  735.                 if( ddrval == DD_OK ) {
  736.                     returnValue = TRUE;
  737.                 } 
  738.             }
  739.         } else {
  740.             ErrMsg("can't set display mode %d x %d",Width,Height);
  741.         }
  742.     }
  743.     return returnValue;
  744. }
  745.  
  746.  
  747. BOOL
  748. CreateSysMemSurface( VOID )
  749. {
  750.     DDSURFACEDESC ddsd;
  751.     ULONG returnValue;
  752.  
  753.     // clear out out stuff
  754.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  755.     ddsd.dwSize = sizeof( ddsd );
  756.  
  757.     // build a surface in system memory
  758.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  759.     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
  760.     
  761.     ddsd.dwHeight = 240;
  762.     ddsd.dwWidth = 320;
  763.     returnValue = pDirectDrawObj->CreateSurface( &ddsd, &pSysMemBuf, NULL );
  764.     if( DD_OK == returnValue ) {
  765.         return TRUE;
  766.     }
  767.  
  768.     return FALSE;
  769. }
  770.  
  771. ULONG
  772. GetStretchFPS( int width, int height )
  773. {
  774.     ULONG time;
  775.     HRESULT ddrval;
  776.     DDSURFACEDESC ddsd;
  777.     DDBLTFX     ddbltfx;
  778.     ULONG FrameCount;
  779.  
  780.     // set the mode (and create the surfaces)
  781.     if( InitFullScreen( width, height ) ) {
  782.         // get the system memory surface
  783.         if( CreateSysMemSurface() ) {
  784.  
  785.             // build the ROP for the blt
  786.             ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
  787.             ddbltfx.dwSize = sizeof( ddbltfx );
  788.             ddbltfx.dwROP = SRCCOPY;
  789.  
  790.             time = timeGetTime();
  791.             // wait for a seconds for the mode to settle out
  792.             // (I don't need to do this.. I'm just paranoid)
  793.             while( (timeGetTime() - time) < 1000);
  794.             FrameCount = 0;
  795.             time = timeGetTime();
  796.  
  797.             // Initialize the surface description structure
  798.             ZeroMemory(&ddsd, sizeof(ddsd));
  799.             ddsd.dwSize=sizeof(ddsd);
  800.  
  801.             ddrval = 0;
  802.             // do this for 5 seconds
  803.             while( ((timeGetTime() - time) < 5000) && (DD_OK == ddrval) ) {
  804.                 // simluate rendering and off screen frame (with a copy)
  805.                 ddrval = pSysMemBuf->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
  806.                 if (FAILED(ddrval))
  807.                 {
  808.                     FrameCount=0;
  809.                     break;
  810.                 }
  811.  
  812.                 DwordMemCopy_Pitch( pSource, ddsd.lpSurface, ddsd.dwHeight, ddsd.dwWidth, ddsd.lPitch, 1);
  813.  
  814.                 ddrval = pSysMemBuf->Unlock( NULL );
  815.                 if (FAILED(ddrval))
  816.                 {
  817.                     FrameCount=0;
  818.                     break;
  819.                 }
  820.  
  821.                 // blt the system buffer into the back buffer
  822.                 ddrval = pOffScreenBuf->Blt( NULL, pSysMemBuf, NULL, DDBLT_ROP | DDBLT_WAIT, &ddbltfx);
  823.                 if (FAILED(ddrval))
  824.                 {
  825.                     FrameCount=0;
  826.                     break;
  827.                 }
  828.  
  829.                 // flip the back buffer on screen
  830.                 ddrval = pOnScreenBuf->Flip( NULL, DDFLIP_WAIT );
  831.                 if (FAILED(ddrval))
  832.                 {
  833.                     FrameCount=0;
  834.                     break;
  835.                 }
  836.  
  837.                 FrameCount++;
  838.             }
  839.         }
  840.         pDirectDrawObj->RestoreDisplayMode();
  841.         if( DD_OK != ddrval ) {
  842.             ErrMsg("Test failure %X",ddrval);
  843.         }
  844.  
  845.         pOffScreenBuf->Release();
  846.         pOffScreenBuf = NULL;
  847.         pOnScreenBuf->Release();
  848.         pOnScreenBuf = NULL;
  849.         pSysMemBuf->Release();
  850.         pSysMemBuf = NULL;
  851.     }
  852.     return FrameCount;
  853. }
  854.  
  855. ULONG GetFPS( int width, int height )
  856. {
  857.     ULONG time;
  858.     DDSURFACEDESC ddsd;
  859.     HRESULT ddrval;
  860.     ULONG FrameCount;
  861.  
  862.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  863.     ddsd.dwSize = sizeof( ddsd );
  864.  
  865.     // set the mode (and setup the surfaces)    
  866.     if( InitFullScreen( width, height ) )
  867.     {
  868.         time = timeGetTime();
  869.         // wait for a seconds for the mode to settle out
  870.         // (I don't need to do this, I'm just paranoid)
  871.         while( (timeGetTime() - time) < 1000);
  872.         ddrval = DD_OK;
  873.         FrameCount = 0;
  874.         time = timeGetTime();
  875.         while( ((timeGetTime() - time) < 5000) && (ddrval == DD_OK) )
  876.         {
  877.             // simluate a render into the back buffer with a copy
  878.             ddrval = pOffScreenBuf->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
  879.             if (FAILED(ddrval))
  880.             {
  881.                 FrameCount=0;
  882.                 break;
  883.             }
  884.             // Stuff some Junk into the offscreen surface
  885.             DwordMemCopy_Pitch( pSource, ddsd.lpSurface, ddsd.dwHeight, ddsd.dwWidth, ddsd.lPitch, 1 );
  886.  
  887.             ddrval = pOffScreenBuf->Unlock( NULL );
  888.             if (FAILED(ddrval))
  889.             {
  890.                 FrameCount=0;
  891.                 break;
  892.             }
  893.  
  894.             // flip the off screen surface on screen
  895.             ddrval = pOnScreenBuf->Flip( NULL, DDFLIP_WAIT );
  896.             if (FAILED(ddrval))
  897.             {
  898.                 FrameCount=0;
  899.                 break;
  900.             }
  901.  
  902.             FrameCount++;
  903.         }
  904.         pDirectDrawObj->RestoreDisplayMode();
  905.         if( FAILED(ddrval) )
  906.             ErrMsg("Test failure %X",ddrval);
  907.         pOffScreenBuf->Release();
  908.         pOffScreenBuf = NULL;
  909.         pOnScreenBuf->Release();
  910.         pOnScreenBuf = NULL;
  911.     }
  912.  
  913.     return FrameCount;
  914. }
  915.  
  916. /*****************************************************************************
  917.  *
  918.  * dprintf() is called by the DPF macro if DEBUG is defined at compile time.
  919.  *
  920.  * The messages will be send to COM1: like any debug message. To
  921.  * enable debug output, add the following to WIN.INI :
  922.  *
  923.  * [debug]
  924.  * QA=1
  925.  *
  926.  ****************************************************************************/
  927.  
  928. #ifdef DEBUG
  929.  
  930. #define MODNAME "QA"
  931.  
  932.  
  933. #define _WINDLL
  934. #include <stdarg.h>
  935.  
  936. void FAR CDECL dprintf(LPSTR szFormat, ...)
  937. {
  938.     char ach[128];
  939.     va_list va;
  940.     
  941.     static BOOL fDebug = -1;
  942.     
  943.     if (fDebug == -1) {
  944.         fDebug = GetProfileIntA("Debug", MODNAME, TRUE);
  945.     }
  946.     
  947.     if (!fDebug) return;
  948.  
  949.     
  950.     
  951.     lstrcpyA(ach, MODNAME ": ");
  952.     va_start(va, szFormat);
  953.     wvsprintfA(ach+lstrlenA(ach),szFormat,(LPSTR)va);
  954.     va_end(va);
  955.     lstrcatA(ach, "\r\n");
  956.     
  957.     OutputDebugStringA(ach);
  958. }
  959.  
  960. #endif
  961.  
  962.