home *** CD-ROM | disk | FTP | other *** search
/ Inside Multimedia 1995 July / IMM0795.ISO / share / os2 / sysbench / src / pmb_dive.c < prev    next >
C/C++ Source or Header  |  1994-11-05  |  16KB  |  618 lines

  1.  
  2. // SysBench DIVE test module
  3. // made for the warp II beta toolkit. Must probably be modified to run on OS/2 3.0
  4.  
  5.  
  6. #define INCL_WIN
  7. #define INCL_GPI
  8. #define INCL_DOS
  9. #include <os2.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #define  _MEERROR_H_
  13. #include "mmioos2.h"                   /* It is from MMPM toolkit           */
  14. #include "dive.h"
  15. #include "fourcc.h"
  16. #include "pmb.h"
  17. #include "types.h"
  18.  
  19. #define ID_WINDOW 8000
  20. #define PMB_DIVE_CLASS "SysBench dive winclass"
  21. #define MIN_DIVE_TIME 10.0
  22. #define MIN_DIVE2_TIME 1.0
  23. #define MIN_MEASURE 0.1
  24. #define MARGINAL 1.1
  25. #define PI 3.14159265358979323846
  26.  
  27. //static HAB  hab;
  28.  
  29. extern double cos(double);
  30. extern double sin(double);
  31. extern void err(char* s);
  32. extern void warn(char* s);
  33. extern void log(char* s);
  34. //extern HAB anchorblock(void);
  35. extern double rtime(void);    // real time in seconds
  36. extern double dtime(void);    // used CPU time in seconds
  37. extern double test_time;
  38.  
  39. VOID APIENTRY paint_videobw(ULONG unused);
  40. VOID APIENTRY paint_rot(ULONG unused);
  41. VOID APIENTRY paint_ms11(ULONG unused);
  42. VOID APIENTRY paint_ms12(ULONG unused);
  43. VOID APIENTRY paint_ms125(ULONG unused);
  44. static MRESULT EXPENTRY DiveWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
  45. static void Open(void *paintfun);
  46. static void Close(void);
  47. _Inline void clr_lines(s32 y, s32 lines);
  48. _Inline void disp_lines(u8* buf, s32 y, s32 lines);
  49. _Inline void disp_lines2(u8* src, u8* dest, s32 yin, s32 yout);
  50. _Inline s32 fun(s32 x, double param);
  51.  
  52. static HWND hwndClient = NULLHANDLE;         /* Client area window handle    */
  53. static HWND hwndFrame = NULLHANDLE;          /* Frame window handle          */
  54. static HMQ  hmq;
  55. static ULONG flCreate;                       /* Window creation control flags*/
  56. static HAB bkHab;
  57. static TID paint_tid;
  58. static double result;
  59. static char* framebuf; // the main framebuffer
  60. static DIVE_CAPS dc;
  61.  
  62. static void Open(void *paintfun) {
  63.   s32 w,h, x,y;
  64.   RECTL rctl, rctlScreen;
  65.   QMSG qmsg;                            /* Message from message queue   */
  66.   RECTL rect;
  67.   hwndClient = NULLHANDLE;         /* Client area window handle    */
  68.   hwndFrame = NULLHANDLE;          /* Frame window handle          */
  69. //  hab = anchorblock();
  70.  
  71.   if ((bkHab = WinInitialize(0)) == 0L) /* Initialize PM     */
  72.     err("Can't get anchor block handle for background thread");
  73.  
  74.   if ((hmq = WinCreateMsgQueue( bkHab, 0 )) == 0L)/* Create a msg queue */
  75.     err("Can't create message queue for graphics test window");
  76.  
  77.   if (!WinRegisterClass(bkHab, (PSZ)PMB_DIVE_CLASS, (PFNWP)DiveWindowProc, 0, 0)) {
  78.     err("DIVE test error: can't register class for child test window");
  79.   }
  80.  
  81.   flCreate = FCF_TASKLIST;
  82.  
  83.   if ((hwndFrame = WinCreateStdWindow(
  84.                HWND_DESKTOP,            /* Desktop window is parent     */
  85.                0,                       /* window styles           */
  86.                &flCreate,               /* Frame control flag           */
  87.                PMB_DIVE_CLASS,    /* Client window class name     */
  88.                "SysBench dive test window",    /* window text               */
  89.                0,                       /* No special class style       */
  90.                (HMODULE)0L,             /* Resource is in .EXE file     */
  91.                ID_WINDOW,               /* Frame window identifier      */
  92.                &hwndClient              /* Client window handle         */
  93.                )) == 0L)
  94.     err("Can't create dive test window");
  95.  
  96.   WinQueryWindowRect(HWND_DESKTOP, &rect);
  97.   WinSetWindowPos(hwndFrame, HWND_TOP, rect.xLeft, rect.yBottom, 
  98.     rect.xRight-rect.xLeft+1, rect.yTop-rect.yBottom+1, SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW | SWP_ZORDER);
  99.  
  100.   DosCreateThread(&paint_tid, (PFNTHREAD)paintfun, 0, 0, 64000);
  101.   while( WinGetMsg( bkHab, &qmsg, 0L, 0, 0 ) )
  102.     WinDispatchMsg( bkHab, &qmsg );
  103. }
  104.  
  105. static void Close(void) {
  106.   WinDestroyWindow(hwndFrame);           /* Tidy up...                   */
  107.   WinDestroyMsgQueue( hmq );             /* Tidy up...                   */
  108.   WinTerminate(bkHab);
  109. }
  110.  
  111. double pmb_dive_bw(void) {
  112.   Open((void*)paint_videobw);
  113.   Close();
  114.   return result;
  115. }
  116.  
  117. double pmb_dive_rot(void) {
  118.   Open((void*)paint_rot);
  119.   Close();
  120.   return result;
  121. }
  122.  
  123. double pmb_dive_ms11(void) {
  124.   Open((void*)paint_ms12);
  125.   Close();
  126.   return result;
  127. }
  128.  
  129. double pmb_dive_ms12(void) {
  130.   Open((void*)paint_ms12);
  131.   Close();
  132.   return result;
  133. }
  134.  
  135. double pmb_dive_ms125(void) {
  136.   Open((void*)paint_ms12);
  137.   Close();
  138.   return result;
  139. }
  140.  
  141. static MRESULT EXPENTRY 
  142. DiveWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  143. {
  144.   switch( msg )
  145.   {
  146.     case WM_CREATE:
  147.       break;
  148.  
  149.     case WM_COMMAND:
  150.       break;
  151.  
  152.     case WM_ERASEBACKGROUND:
  153.       return (MRESULT)( FALSE ); // TRUE -> yes, erase the background
  154.  
  155.     case WM_PAINT:
  156.       {
  157.         HPS    hps;
  158.         RECTL  rc; 
  159.         POINTL pt; 
  160.                  
  161.         hps = WinBeginPaint( hwnd, 0L, &rc );
  162.         GpiSetColor( hps, CLR_BLACK );      // colour of the text,   
  163.         GpiSetBackColor( hps, CLR_BLACK );   // its background and    
  164.         GpiSetBackMix( hps, BM_OVERPAINT );  // how it mixes,         
  165.         GpiSetMix( hps, FM_OVERPAINT );  // how it mixes,         
  166. //        WinFillRect(hps, &rc, CLR_BLACK);
  167.         WinEndPaint( hps );                  // Drawing is complete   
  168.         break;
  169.       }
  170.     case WM_CLOSE:
  171.       exit(1); //WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 );
  172.       break;
  173.     default:
  174.       return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  175.   }
  176.   return (MRESULT)FALSE;
  177. }
  178.  
  179. VOID APIENTRY paint_videobw(ULONG unused) {
  180.   HPS hps;
  181.   POINTL p1, p2;
  182.   double t1, t2;
  183.   RECTL rc;
  184.   HDIVE hDive;
  185.   PVOID apa;
  186.   ULONG ret;
  187.   PDIVE_CAPS pdc;
  188.   s32 i, j, c, runs, runs_10, framesize, sh, scanlen, frames;
  189.   RECTL rect;
  190.   char* framecopy;
  191.  
  192.   memset(&dc, 0, sizeof(dc));
  193.   dc.ulStructLen = sizeof(dc);
  194.   dc.ulFormatLength = 0;
  195.   ret = DiveQueryCaps(&dc, DIVE_BUFFER_SCREEN);
  196.   if (DIVE_SUCCESS != ret) {
  197.     if (ret == DIVE_ERR_INSUFFICIENT_LENGTH) {
  198.       dc.pFormatData = calloc(dc.ulFormatLength,1);
  199.       ret = DiveQueryCaps(&dc, DIVE_BUFFER_SCREEN); // let's try again
  200.       if (DIVE_SUCCESS != ret) {
  201.         err("Error in call to DiveQueryCaps()");
  202.       }
  203.     } else {
  204.       err("Error in call to DiveQueryCaps()");
  205.     }
  206.   }
  207.  
  208.   if (DiveOpen(&hDive, FALSE, &apa)) {
  209.     WinPostMsg( hwndClient, WM_QUIT, (MPARAM)0,(MPARAM)0 );
  210.     err("Error in DiveOpen() call");
  211.   }
  212.  
  213.   framebuf = (char*)apa;
  214.  
  215.   WinQueryWindowRect(HWND_DESKTOP, &rect);
  216.   ret = DiveAcquireFrameBuffer(hDive, &rect);
  217.   if (ret != DIVE_SUCCESS) {
  218.     err("Error in DiveAcquireFrameBuffer()");
  219.   }
  220.  
  221.   framesize = dc.ulVerticalResolution * dc.ulScanLineBytes;
  222.   framecopy = malloc(framesize);
  223.   if (framecopy == null) {
  224.     err("Can't get memory for copy of frame buffer");
  225.   }
  226.  
  227.   memcpy(framecopy, framebuf, framesize);
  228.  
  229.   frames = 0;
  230.   sh = dc.ulVerticalResolution;
  231.   scanlen = dc.ulScanLineBytes;
  232.  
  233.   runs = 10;
  234.  
  235.   while (1) {
  236.  
  237.     frames = 0;
  238.     t1 = dtime();
  239.  
  240.     for (i = 0; i < runs; i++) {
  241.       frames++;
  242.       j = i % (sh-1) + 1;
  243.       memcpy(framebuf, framecopy+(sh-j)*scanlen, j*scanlen);
  244.       memcpy(framebuf + j*scanlen, framecopy, (sh-j)*scanlen);
  245.     } 
  246.  
  247.     t2 = dtime();
  248.  
  249.     if ((t2 - t1) < MIN_DIVE_TIME) {
  250.       if ((t2 - t1) < MIN_MEASURE) {
  251.         runs = MIN_DIVE_TIME/MIN_MEASURE*runs;
  252.       } else {
  253.         runs = MIN_DIVE_TIME*MARGINAL/(t2-t1)*runs;
  254.       }
  255.     } else {
  256.       break;
  257.     }
  258.   }
  259.  
  260.   result = ((double) frames * scanlen * sh) / (t2-t1);
  261.   test_time = (t2-t1);
  262.  
  263.   DiveDeacquireFrameBuffer(hDive);
  264.   DiveClose(hDive);
  265.   free(dc.pFormatData);
  266.   WinPostMsg( hwndClient, WM_QUIT, (MPARAM)0,(MPARAM)0 );
  267. }
  268.  
  269. VOID APIENTRY paint_rot(ULONG unused) {
  270.   HPS hps;
  271.   POINTL p1, p2;
  272.   double t1, t2;
  273.   RECTL rc;
  274.   HDIVE hDive;
  275.   PVOID apa;
  276.   ULONG ret;
  277.   PDIVE_CAPS pdc;
  278.   s32 i, j, c, runs, runs_10, framesize, sh, scanlen, frames, yin, yout, x, y;
  279.   RECTL rect;
  280.   char* framecopy;
  281.   s32 speed, rev, arg_nrev, sh2, wh, wh2;
  282.   double phase = 0.0, phase_steps, c1, c2, c3, c4, c5, c6, c7, c8;
  283.   bool forw;
  284.  
  285.   memset(&dc, 0, sizeof(dc));
  286.   dc.ulStructLen = sizeof(dc);
  287.   dc.ulFormatLength = 0;
  288.   ret = DiveQueryCaps(&dc, DIVE_BUFFER_SCREEN);
  289.   if (DIVE_SUCCESS != ret) {
  290.     if (ret == DIVE_ERR_INSUFFICIENT_LENGTH) {
  291.       dc.pFormatData = calloc(dc.ulFormatLength,1);
  292.       ret = DiveQueryCaps(&dc, DIVE_BUFFER_SCREEN); // let's try again
  293.       if (DIVE_SUCCESS != ret) {
  294.         err("Error in call to DiveQueryCaps()");
  295.       }
  296.     } else {
  297.       err("Error in call to DiveQueryCaps()");
  298.     }
  299.   }
  300.  
  301.   if (DiveOpen(&hDive, FALSE, &apa)) {
  302.     WinPostMsg( hwndClient, WM_QUIT, (MPARAM)0,(MPARAM)0 );
  303.     err("Error in DiveOpen() call");
  304.   }
  305.  
  306.   framebuf = (char*)apa;
  307.  
  308.   WinQueryWindowRect(HWND_DESKTOP, &rect);
  309.   ret = DiveAcquireFrameBuffer(hDive, &rect);
  310.   if (ret != DIVE_SUCCESS) {
  311.     err("Error in DiveAcquireFrameBuffer()");
  312.   }
  313.  
  314.   framesize = dc.ulVerticalResolution * dc.ulScanLineBytes;
  315.   framecopy = malloc(framesize);
  316.   if (framecopy == null) {
  317.     err("Can't get memory for copy of frame buffer");
  318.   }
  319.  
  320.   memcpy(framecopy, framebuf, framesize);
  321.  
  322.   frames = 0;
  323.   sh = dc.ulVerticalResolution;
  324.   scanlen = dc.ulScanLineBytes;
  325.  
  326.   runs = 10;
  327.  
  328.   // First, find out the approximate speed of this display
  329.   while (1) {
  330.     frames = 0;
  331.     t1 = dtime();
  332.     for (i = 0; i < runs; i++) {
  333.       frames++;
  334.       memcpy(framebuf, framecopy, sh*scanlen);
  335.     } 
  336.     t2 = dtime();
  337.     if ((t2 - t1) < MIN_DIVE2_TIME) {
  338.       if ((t2 - t1) < MIN_MEASURE) {
  339.         runs = MIN_DIVE2_TIME/MIN_MEASURE*runs;
  340.       } else {
  341.         runs = MIN_DIVE2_TIME*MARGINAL/(t2-t1)*runs;
  342.       }
  343.     } else {
  344.       break;
  345.     }
  346.   }
  347.  
  348.   // speed = ((double) frames * scanlen * sh) / (t2-t1); // MB/s
  349.   speed = ((double)frames)/(t2-t1); // fps
  350.  
  351.   sh = dc.ulVerticalResolution;
  352.   sh2 = sh/2;
  353.  
  354.   phase_steps = .35/speed;
  355.   arg_nrev = 1;
  356.  
  357.  
  358.   t1 = dtime();  
  359.   frames = 0;
  360.  
  361.   goto lab1;  
  362.  
  363. lab1:
  364.  
  365.   for (rev = 0; rev < arg_nrev; rev++) {
  366.     for (phase = 0.0; phase < 2.0*PI; phase += phase_steps) {
  367.       frames++;
  368.       wh2 = sh2 * cos(phase);
  369.       if (wh2 < 0) {
  370.         forw = false;
  371.         wh2 = -wh2;
  372.       } else {
  373.         forw = true;
  374.       }
  375.       wh = wh2 << 1;
  376.       if (forw) {
  377.         clr_lines(0, sh2-wh2);
  378.         for (i = 0; i < wh; i++) {
  379.           disp_lines(framecopy+((i*sh)/wh)*dc.ulScanLineBytes, i+sh2-wh2, 1);
  380.         }
  381.         clr_lines(sh2+wh2, sh2-wh2);
  382.       } else {
  383.         clr_lines(0, sh2-wh2);
  384.         for (i = 0; i < wh; i++) {
  385.           disp_lines(framecopy+(((wh-1-i)*sh)/wh)*dc.ulScanLineBytes, i+sh2-wh2, 1);
  386.         }
  387.         clr_lines(sh2+wh2, sh2-wh2);
  388.       }
  389.     }
  390.   }
  391.  
  392.  
  393.   phase_steps *= 1.4; // a little faster than the rotation
  394.  
  395.  
  396.   c1 = 24.0 * (double)dc.ulVerticalResolution / 768.0;
  397.   c2 = 2.0 * (double)dc.ulVerticalResolution / 768.0;
  398.   c3 = 4.0/(dc.ulVerticalResolution/6.0/PI);
  399.   c4 = .7/(dc.ulVerticalResolution/6.0/PI);
  400.   c5 = 1.0;
  401.   c6 = 2.3;
  402.   c7 = 0.0;
  403.   c8 = 1.0;
  404.   for (rev = 0; rev < arg_nrev; rev++) {
  405.     for (phase = 0.0; phase < 2.0*PI; phase += phase_steps) {
  406.       frames++;
  407.       for (yin = 0; yin < sh; yin++) {
  408.         yout = ((double)yin) + c1 * sin(phase * c5 + c7 + yin * c4) +
  409.                                c2 * sin(phase * c6 + c8 + yin * c3);
  410.         if (yout < 0 || yout >= dc.ulHorizontalResolution) {
  411.           clr_lines(yin, 1);
  412.         } else {
  413.           disp_lines2(framecopy, framebuf, yout, yin);
  414.         }
  415.       }
  416.     }
  417.   }
  418.  
  419. /*
  420.   for (i = 0; i < 40; i++) {
  421.     frames++;
  422.     c = 20;
  423.     for (x = 0; x < 1024/2; x++) {
  424.       j = -((c * (x - 1024/2)) / (1024/2)) * scanlen;
  425.       for (y = 0; y < 768*scanlen-j; y += scanlen)
  426.         *(framebuf + x + y) = *(framebuf + x + y + j);
  427.     }
  428.     for (x = 1024/2; x < 1024; x++) {
  429.       j = ((c * (x - 1024/2)) / (1024/2)) * scanlen;
  430.       for (y = 767*scanlen; y >= j; y -= scanlen)
  431.         *(framebuf + x + y) = *(framebuf + x + y - j);
  432.     }
  433.  
  434.     for (y = 0; y < 768/2; y++) {
  435.       j = (c * (768/2 - y)) / (768/2);
  436.       memmove(framebuf + j + y*scanlen, framebuf + y*scanlen, scanlen - j);
  437.     }
  438.     for (y = 768/2; y < 768; y++) {
  439.       j = -(c * (768/2 - y)) / (768/2);
  440.       memmove(framebuf + y*scanlen, framebuf + j + y*scanlen, scanlen - j);
  441.     }
  442.   }
  443. */
  444.  
  445.   t2 = dtime();  
  446.  
  447.   result = ((double) frames ) / (t2-t1);
  448.   test_time = (t2-t1);
  449.  
  450.   DiveDeacquireFrameBuffer(hDive);
  451.   DiveClose(hDive);
  452.   free(dc.pFormatData);
  453.   WinPostMsg( hwndClient, WM_QUIT, (MPARAM)0,(MPARAM)0 );
  454. }
  455.  
  456. _Inline void
  457. clr_lines(s32 y, s32 lines) {
  458.   s32 n = (lines*dc.ulScanLineBytes) >> 4;
  459.   u32* p = (u32*)(framebuf + y*dc.ulScanLineBytes);
  460.   s32 i;
  461.   for(i = 0; i < n; i++) {
  462.     *p++ = 0; // speed man...
  463.     *p++ = 0;
  464.     *p++ = 0;
  465.     *p++ = 0;
  466.   }
  467. }
  468.  
  469. _Inline void
  470. disp_lines(u8* buf, s32 y, s32 lines) {
  471.  
  472.   memcpy(framebuf + y*dc.ulScanLineBytes, buf, lines*dc.ulScanLineBytes);
  473.  
  474. /*
  475.   s32 n = (lines*dc.ulScanLineBytes) >> 4;
  476.   u32* p = (u32*)(framebuf + y*dc.ulScanLineBytes);
  477.   u32* p2 = (u32*)buf;
  478.   s32 i;
  479.   for(i = 0; i < n; i++) {
  480.     *p++ = *p2++;
  481.     *p++ = *p2++;
  482.     *p++ = *p2++;
  483.     *p++ = *p2++;
  484.   }
  485. */
  486. }
  487.  
  488. _Inline void
  489. disp_lines2(u8* src, u8* dest, s32 yin, s32 yout) {
  490.   s32 scanlen;
  491.   scanlen = dc.ulScanLineBytes;
  492.   memcpy(dest + yout * scanlen, src + yin * scanlen, scanlen);
  493. }
  494.  
  495. /*
  496. inline static void
  497. disp_lines2(u8* src, u8* dest, s32 yin, s32 yout, s32 offs) {
  498.   s32 scanlen;
  499.   scanlen = dc.ulScanLineBytes;
  500.   offs = (offs * (s32)dc.ulScanLineBytes) / (s32)dc.ulHorizontalResolution;
  501.   if (offs > 0 && offs < scanlen) {
  502.     memcpy(dest + yout * scanlen + offs, src + yin * scanlen, scanlen - offs);
  503.     memset(dest + yout * scanlen, 0, offs);
  504.   } else if (offs < 0 && offs > -scanlen) {
  505.     memcpy(dest + yout * scanlen, src + yin * scanlen - offs, scanlen + offs);
  506.     memset(dest + yout * scanlen + (scanlen + offs), 0, -offs);
  507.   } else {
  508.     memcpy(dest + yout * scanlen, src + yin * scanlen, scanlen);
  509.   }
  510. }
  511. */
  512.  
  513.  
  514.  
  515. _Inline s32
  516. fun(s32 x, double param) {
  517.   s32 yout;
  518.   yout = ((double)x) + 20.0 * sin(param+x/(dc.ulVerticalResolution/6.0/PI)) +
  519.          10.0 * sin(param*2.3+1.0+3*x/(dc.ulVerticalResolution/6.0/PI));
  520.   if (yout < 0 || yout >= dc.ulHorizontalResolution) 
  521.     yout = -1;
  522.   return yout;
  523. }
  524.  
  525.  
  526.  
  527. // this function is NOT ready! It is under construction
  528. VOID APIENTRY paint_ms12(ULONG unused) {
  529.   HPS hps;
  530.   POINTL p1, p2;
  531.   double t1, t2;
  532.   RECTL rc;
  533.   HDIVE hDive;
  534.   PVOID apa;
  535.   ULONG ret;
  536.   PDIVE_CAPS pdc;
  537.   s32 i, j, c, runs, runs_10, framesize, sh, scanlen, frames;
  538.   RECTL rect;
  539.   char* framecopy;
  540.  
  541.   memset(&dc, 0, sizeof(dc));
  542.   dc.ulStructLen = sizeof(dc);
  543.   dc.ulFormatLength = 0;
  544.   ret = DiveQueryCaps(&dc, DIVE_BUFFER_SCREEN);
  545.   if (DIVE_SUCCESS != ret) {
  546.     if (ret == DIVE_ERR_INSUFFICIENT_LENGTH) {
  547.       dc.pFormatData = calloc(dc.ulFormatLength,1);
  548.       ret = DiveQueryCaps(&dc, DIVE_BUFFER_SCREEN); // let's try again
  549.       if (DIVE_SUCCESS != ret) {
  550.         err("Error in call to DiveQueryCaps()");
  551.       }
  552.     } else {
  553.       err("Error in call to DiveQueryCaps()");
  554.     }
  555.   }
  556.  
  557.   if (DiveOpen(&hDive, FALSE, &apa)) {
  558.     WinPostMsg( hwndClient, WM_QUIT, (MPARAM)0,(MPARAM)0 );
  559.     err("Error in DiveOpen() call");
  560.   }
  561.  
  562.   framebuf = (char*)apa;
  563.  
  564. /*  WinQueryWindowRect(HWND_DESKTOP, &rect);
  565.   ret = DiveAcquireFrameBuffer(hDive, &rect);
  566.   if (ret != DIVE_SUCCESS) {
  567.     err("Error in DiveAcquireFrameBuffer()");
  568.   }
  569. */
  570.   framesize = dc.ulVerticalResolution * dc.ulScanLineBytes;
  571.   framecopy = malloc(framesize);
  572.   if (framecopy == null) {
  573.     err("Can't get memory for copy of frame buffer");
  574.   }
  575.  
  576.   memcpy(framecopy, framebuf, framesize);
  577.  
  578.   frames = 0;
  579.   sh = dc.ulVerticalResolution;
  580.   scanlen = dc.ulScanLineBytes;
  581.  
  582.   runs = 10;
  583.  
  584.   while (1) {
  585.  
  586.     frames = 0;
  587.     t1 = dtime();
  588.  
  589.     for (i = 0; i < runs; i++) {
  590.       frames++;
  591.       j = i % (sh-1) + 1;
  592.       memcpy(framebuf, framecopy+(sh-j)*scanlen, j*scanlen);
  593.       memcpy(framebuf + j*scanlen, framecopy, (sh-j)*scanlen);
  594.     } 
  595.  
  596.     t2 = dtime();
  597.  
  598.     if ((t2 - t1) < MIN_DIVE_TIME) {
  599.       if ((t2 - t1) < MIN_MEASURE) {
  600.         runs = MIN_DIVE_TIME/MIN_MEASURE*runs;
  601.       } else {
  602.         runs = MIN_DIVE_TIME*MARGINAL/(t2-t1)*runs;
  603.       }
  604.     } else {
  605.       break;
  606.     }
  607.   }
  608.  
  609.   result = ((double) frames * scanlen * sh) / (t2-t1);
  610.   test_time = (t2-t1);
  611.  
  612. //  DiveDeacquireFrameBuffer(hDive);
  613.   DiveClose(hDive);
  614.   free(dc.pFormatData);
  615.   WinPostMsg( hwndClient, WM_QUIT, (MPARAM)0,(MPARAM)0 );
  616. }
  617.  
  618.