home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / misc / rmstats.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  9KB  |  307 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File: rmstats.cpp
  6.  *
  7.  ***************************************************************************/
  8. #include "rmfull.h"
  9.  
  10. /*
  11.  * GLOBAL VARIABLES
  12.  */
  13. extern D3DAppInfo* d3dapp;        /* Pointer to read only collection of DD and D3D
  14.                            objects maintained by D3DApp */
  15. extern rmfullglobals myglobs;        /* collection of global variables */
  16.  
  17. static struct {
  18.     HFONT hFont;
  19.     SIZE szFrameRate;
  20.     SIZE szInfo;
  21. } statglobs;
  22.  
  23.  /************************************************************************
  24.   Frame rate and info text
  25.  ************************************************************************/
  26.  
  27. BOOL
  28. WriteFrameRateBuffer(float fps, long tps)
  29. {
  30.     HRESULT LastError;
  31.     HDC hdc;
  32.     RECT rc;
  33.     char buf1[30], buf2[30], buf[60];
  34.     int len;
  35.  
  36.     if (!myglobs.lpFrameRateBuffer)
  37.     return TRUE;
  38.     if (fps > 0.0f)
  39.         wsprintf(buf1, "%d.%02d fps   ",
  40.                     (int)( fps * 100 ) / 100,
  41.                     (int)( fps * 100 ) % 100);
  42.     else
  43.         buf1[0] = 0;
  44.     if (tps > 0)
  45.         wsprintf(buf2, "%ld tps   ", tps);
  46.     else
  47.         buf2[0] = 0;
  48.     len = wsprintf(buf, "%s%s", buf1, buf2);
  49.     if (!myglobs.lpFrameRateBuffer)
  50.         return FALSE;
  51.     LastError = myglobs.lpFrameRateBuffer->GetDC(&hdc);
  52.     if (LastError != DD_OK) {
  53.     /*
  54.      *  This is not vital, don't report an error.
  55.      */
  56.         return TRUE;
  57.     }
  58.     SelectObject(hdc, statglobs.hFont);
  59.     SetTextColor(hdc, RGB(255,255,0));
  60.     SetBkColor(hdc, RGB(0,0,0));
  61.     SetBkMode(hdc, OPAQUE);
  62.     GetTextExtentPoint32(hdc, buf, len, &statglobs.szFrameRate);
  63.     SetRect(&rc, 0, 0, statglobs.szFrameRate.cx, statglobs.szFrameRate.cy);
  64.     ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, buf, len, NULL);
  65.     myglobs.lpFrameRateBuffer->ReleaseDC(hdc);
  66.     return TRUE;
  67. }
  68.  
  69. BOOL
  70. WriteInfoBuffer(void)
  71. {
  72.     HRESULT LastError;
  73.     HDC hdc;
  74.     RECT rc;
  75.     char buf[40];
  76.     int len;
  77.  
  78.     if (!myglobs.lpInfoBuffer)
  79.     return TRUE;
  80.     if (d3dapp->bFullscreen)
  81.     len = wsprintf(buf, "%dx%dx%d (%s)", d3dapp->ThisMode.w, d3dapp->ThisMode.h, d3dapp->ThisMode.bpp,
  82.                (d3dapp->ThisDriver.Desc.dcmColorModel == D3DCOLOR_MONO) ? "MONO" : "RGB");
  83.     else
  84.     len = wsprintf(buf, "%dx%d (%s)", d3dapp->szClient.cx, d3dapp->szClient.cy, 
  85.                (d3dapp->ThisDriver.Desc.dcmColorModel == D3DCOLOR_MONO) ? "MONO" : "RGB");
  86.     if (!myglobs.lpInfoBuffer)
  87.         return FALSE;
  88.     LastError = myglobs.lpInfoBuffer->GetDC(&hdc);
  89.     if (LastError != DD_OK) {
  90.     /*
  91.      *  This is not vital, don't report an error.
  92.      */
  93.         return TRUE;
  94.     }
  95.  
  96.     SelectObject(hdc, statglobs.hFont);
  97.     SetTextColor(hdc, RGB(255,255,0));
  98.     SetBkColor(hdc, RGB(0,0,0));
  99.     SetBkMode(hdc, OPAQUE);
  100.     GetTextExtentPoint32(hdc, buf, len, &statglobs.szInfo);
  101.     SetRect(&rc, 0, 0, statglobs.szInfo.cx, statglobs.szInfo.cy);
  102.     ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, buf, len, NULL);
  103.     myglobs.lpInfoBuffer->ReleaseDC(hdc);
  104.     return TRUE;
  105. }
  106.  
  107.  
  108. BOOL
  109. InitFontAndTextBuffers(void)
  110. {
  111.     DDCOLORKEY          ddck;
  112.     DDSURFACEDESC       ddsd;
  113.     HDC hdc;
  114.     HRESULT ddrval;
  115.     char dummyinfo[] = "000x000x00 (MONO) 0000";
  116.     char dummyfps[] = "000.00 fps 00000000.00 tps 0000.00 mppps";
  117.    
  118.     /*
  119.      * Create the font.
  120.      */
  121.     RELEASE(myglobs.lpInfoBuffer);
  122.     RELEASE(myglobs.lpFrameRateBuffer);
  123.     if (statglobs.hFont != NULL) {
  124.         DeleteObject(statglobs.hFont);
  125.     }
  126.     statglobs.hFont = CreateFont(
  127.         d3dapp->szClient.cx <= 600 ? 12 : 24,
  128.         0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
  129.         ANSI_CHARSET,
  130.         OUT_DEFAULT_PRECIS,
  131.         CLIP_DEFAULT_PRECIS,
  132.         DEFAULT_QUALITY,
  133.         VARIABLE_PITCH,
  134.         "Arial" );
  135.  
  136.     hdc = GetDC(NULL);
  137.     SelectObject(hdc, statglobs.hFont);
  138.     GetTextExtentPoint(hdc, dummyfps, strlen(dummyfps), &statglobs.szFrameRate);
  139.     GetTextExtentPoint(hdc, dummyinfo, strlen(dummyinfo), &statglobs.szInfo);
  140.     ReleaseDC(NULL, hdc);
  141.  
  142.     memset( &ddsd, 0, sizeof( ddsd ) );
  143.     ddsd.dwSize = sizeof( ddsd );
  144.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  145.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  146.     ddsd.dwHeight = statglobs.szFrameRate.cy;
  147.     ddsd.dwWidth = statglobs.szFrameRate.cx;
  148.     ddrval = D3DAppCreateSurface(&ddsd, &myglobs.lpFrameRateBuffer);
  149.     if (ddrval != DD_OK) {
  150.     Msg("Could not create frame rate buffer.\n%s", D3DAppErrorToString(ddrval));    
  151.         goto exit_with_error;
  152.     }
  153.     memset(&ddck, 0, sizeof(ddck));
  154.     myglobs.lpFrameRateBuffer->SetColorKey(DDCKEY_SRCBLT, &ddck);
  155.     if (!WriteFrameRateBuffer(0.0f, 0)) {
  156.         goto exit_with_error;
  157.     }
  158.     memset( &ddsd, 0, sizeof( ddsd ) );
  159.     ddsd.dwSize = sizeof( ddsd );
  160.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  161.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  162.     ddsd.dwHeight = statglobs.szInfo.cy;
  163.     ddsd.dwWidth = statglobs.szInfo.cx;
  164.     ddrval = D3DAppCreateSurface(&ddsd, &myglobs.lpInfoBuffer);
  165.     if (ddrval != DD_OK) {
  166.     Msg("Could not create info buffer.\n%s", D3DAppErrorToString(ddrval));
  167.     goto exit_with_error;
  168.     }
  169.     memset(&ddck, 0, sizeof(ddck));
  170.     myglobs.lpInfoBuffer->SetColorKey(DDCKEY_SRCBLT, &ddck);
  171.     if (!WriteInfoBuffer())
  172.     goto exit_with_error;
  173.     return TRUE;
  174. exit_with_error:
  175.     RELEASE(myglobs.lpInfoBuffer);
  176.     RELEASE(myglobs.lpFrameRateBuffer);
  177.     if (statglobs.hFont != NULL) {
  178.         DeleteObject(statglobs.hFont);
  179.     }
  180.     return FALSE;
  181. }
  182.  
  183. /*************************************************************************
  184.   Frame rate output.
  185.  *************************************************************************/
  186.  
  187. #define INTERVAL 100
  188.  
  189. char StatTxt[100];
  190. int StatTxtLen;
  191. int count = 0;
  192. int last_polygons = 0;
  193. int this_frames = 0;
  194. time_t last_time;
  195. float fps;
  196. long tps;
  197.  
  198. /*
  199.  * ResetFrameRate
  200.  * Initializes the frame rate counter.
  201.  */
  202. void
  203. ResetFrameRate(void)
  204. {
  205.     last_time = clock();
  206.     count = 0;
  207.     last_polygons = 0;
  208.     this_frames = 0;
  209.     fps = 0.0f; tps = 0;
  210.     StatTxt[0] = 0;
  211.     StatTxtLen = 0;
  212. }
  213.  
  214. BOOL
  215. CalculateFrameRate()
  216. {
  217.     /*
  218.      * Calculate the frame rate and get other stats.
  219.      */
  220.     count++;
  221.     this_frames++;
  222.     if (count == INTERVAL) {
  223.         double t;
  224.     int p, f;
  225.         time_t this_time;
  226.  
  227.         count = 0;
  228.     this_time = clock();
  229.     t = (this_time - last_time) / (double)CLOCKS_PER_SEC;
  230.     last_time = this_time;
  231.  
  232.     p = myglobs.dev->GetTrianglesDrawn() - last_polygons;
  233.     last_polygons = myglobs.dev->GetTrianglesDrawn();
  234.  
  235.     f = this_frames;
  236.     this_frames = 0;
  237.  
  238.         fps = (float)(f / t);
  239.         tps = (long)(p / t);
  240.  
  241.         if (myglobs.bShowFrameRate) {
  242.             if (!WriteFrameRateBuffer(fps, tps))
  243.                 return FALSE;
  244.         }
  245.     }
  246.     return TRUE;
  247. }
  248.  
  249. /*
  250.  * DisplayFrameRate
  251.  * Outputs frame rate info and screen mode to back buffer when appropriate.
  252.  */
  253. BOOL
  254. DisplayFrameRate(int* count, LPD3DRECT lpExtents )
  255. {
  256.     RECT rc;
  257.     int x, y;
  258.     HRESULT ddrval = DD_OK;
  259.     if (myglobs.bShowFrameRate && !myglobs.bSingleStepMode && statglobs.szFrameRate.cx > 0 && statglobs.szFrameRate.cy > 0 &&
  260.         statglobs.szFrameRate.cx < d3dapp->szClient.cx && statglobs.szFrameRate.cy < d3dapp->szClient.cy) {
  261.         SetRect(&rc, 0, 0, statglobs.szFrameRate.cx, statglobs.szFrameRate.cy);
  262.         x = (int)(0.5 * (d3dapp->szClient.cx - statglobs.szFrameRate.cx) + 0.5);
  263.         y = 0;
  264.     if (myglobs.lpFrameRateBuffer)
  265.         ddrval = d3dapp->lpBackBuffer->BltFast(x, y, myglobs.lpFrameRateBuffer, &rc,
  266.                          DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);
  267.     if (ddrval != DD_OK) {
  268.         /*
  269.          * Blting the frame rate has failed. Since it is not vital, we
  270.          * aren't going to report an error.  Check to see if the surfaces
  271.          * have been lost and then return.
  272.          */
  273.         if (ddrval == DDERR_SURFACELOST) {
  274.         d3dapp->lpBackBuffer->Restore();
  275.         myglobs.lpFrameRateBuffer->Restore();
  276.         }
  277.         return TRUE;
  278.     }
  279.     SetRect((LPRECT)(lpExtents), x, y, statglobs.szFrameRate.cx + x, statglobs.szFrameRate.cy);
  280.     ++(*count);
  281.     ++lpExtents;
  282.     }
  283.     if (myglobs.bShowInfo && statglobs.szInfo.cx < d3dapp->szClient.cx && statglobs.szInfo.cy < d3dapp->szClient.cy) {
  284.         SetRect(&rc, 0, 0, statglobs.szInfo.cx, statglobs.szInfo.cy);
  285.         x = (int)(0.5 * (d3dapp->szClient.cx - statglobs.szInfo.cx) + 0.5);
  286.         y = d3dapp->szClient.cy - statglobs.szInfo.cy;
  287.     if (myglobs.lpInfoBuffer)
  288.         ddrval = d3dapp->lpBackBuffer->BltFast(x,y, myglobs.lpInfoBuffer, &rc,
  289.                          DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);
  290.     if (ddrval != DD_OK) {
  291.         /*
  292.          * Blting the info has failed. Since it is not vital, we
  293.          * aren't going to report an error.  Check to see if the surfaces
  294.          * have been lost and then return.
  295.          */
  296.         if (ddrval == DDERR_SURFACELOST) {
  297.         d3dapp->lpBackBuffer->Restore();
  298.         myglobs.lpInfoBuffer->Restore();
  299.         }
  300.         return TRUE;
  301.     }
  302.     SetRect((LPRECT)(lpExtents), x, y, x + statglobs.szInfo.cx, y + statglobs.szInfo.cy);
  303.     ++(*count);
  304.     }
  305.     return TRUE;
  306. }
  307.