performance.c 7.76 KB
/*====================================================================
 * performance.c
 *
 * Copyright 1995, Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
 * Inc.; the contents of this file may not be disclosed to third
 * parties, copied or duplicated in any form, in whole or in part,
 * without the prior written permission of Silicon Graphics, Inc.
 *
 * RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to
 * restrictions as set forth in subdivision (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS
 * 252.227-7013, and/or in similar or successor clauses in the FAR,
 * DOD or NASA FAR Supplement. Unpublished - rights reserved under the
 * Copyright Laws of the United States.
 *====================================================================*/

/*========================*/

#include <ultra64.h>
#include <ultralog.h>
#include <os.h>

#include <assert.h>

#include "audio.h"
#include "gfx.h"
#include "performance.h"
#include "sequence.h"
#include "UIpane.h"
#include "font_ext.h"



static Performance      sPerformance;

static void __PerfItemInit (UIItem *pItem, int id);
static void __PerfStatsDrawProc (UIItem *pItem, Gfx **ppGfx);

static void __PerfPaneDrawProc (UIPane *pPane, Gfx **ppGfx);
static char __PerfHandleEventProc (UIPane *pPane, UIEvent *pEvent);

static char __PerfHandleMouseDown (UIPane *pPane, Point *pPt);
static char __PerfHandleMouseUp (UIPane *pPane, Point *pPt);
static char __PerfHandleButtonDown (UIPane *pPane, int button);

void Stats_Init (Stats *pStats, s32 limit);
void Stats_Clear (Stats *pStats);
void Stats_AddSample (Stats *pStats, s32 frameSample);
void Stats_Draw (Stats *pStats, Rect *pRect, Gfx **ppGfx);


void
Perf_Init (UIPane **ppPane)
{
    UIItem      *pItem;
    int         i;
    
    /* Initialize the performance object's pane. */
    Pane_Init (&sPerformance.fPane);
    sPerformance.fPane.numItems = kNumPerfItems;
    sPerformance.fPane.itemList = sPerformance.fItemList;
    sPerformance.fPane.pData = &sPerformance;
    sPerformance.fPane.DrawProc = __PerfPaneDrawProc;
    sPerformance.fPane.HandleEventProc = __PerfHandleEventProc;
    SetRect (&sPerformance.fPane.bounds, kPerf_l, kPerf_t, kPerf_l + kPerf_w, kPerf_t + kPerf_h);
    

    /* Initialize each of the transport's pane's items. */
    for (i=0; i<sPerformance.fPane.numItems; i++)
    {
        pItem = &sPerformance.fPane.itemList[i];

        __PerfItemInit (pItem, i);
    }


    /* Return the pane's address to the caller. */
    *ppPane = &sPerformance.fPane;
}


static void
__PerfItemInit (UIItem *pItem, int id)
{
    Item_Init (pItem, id);
    
    pItem->pPane = &sPerformance.fPane; 
    pItem->DrawProc = __PerfStatsDrawProc;

    switch (id)
    {
      case kCPUHistItemID:
	  Stats_Init (&sPerformance.fCPUStats, 833333);
          SetRect (&pItem->bounds, kCPUHistItem_l, kCPUHistItem_t, kCPUHistItem_l + kCPUHistItem_w, kCPUHistItem_t + kCPUHistItem_h);
          break;

      case kRSPHistItemID:
	  Stats_Init (&sPerformance.fRSPStats, 833333);
          SetRect (&pItem->bounds, kRSPHistItem_l, kRSPHistItem_t, kRSPHistItem_l + kRSPHistItem_w, kRSPHistItem_t + kRSPHistItem_h);
          break;

      case kVoxHistItemID:
	  Stats_Init (&sPerformance.fVoxStats, MAX_SYNTH_VVOICES);
          SetRect (&pItem->bounds, kVoxHistItem_l, kVoxHistItem_t, kVoxHistItem_l + kVoxHistItem_w, kVoxHistItem_t + kVoxHistItem_h);
          break;
    }
}


void
Perf_ClearStats (void)
{
    Stats_Clear (&sPerformance.fCPUStats);
    Stats_Clear (&sPerformance.fRSPStats);
    Stats_Clear (&sPerformance.fVoxStats);
}


void
Perf_CPUSample (s32 frameSample)
{
    Stats_AddSample (&sPerformance.fCPUStats, frameSample);
}


void
Perf_RSPSample (s32 frameSample)
{
    Stats_AddSample (&sPerformance.fRSPStats, frameSample);
}


void
Stats_Init (Stats *pStats, s32 limit)
{
    pStats->fLimit = limit;

    Stats_Clear (pStats);

    Hist_Init (&pStats->fHist, kHistSize, limit);
}


void
Stats_Clear (Stats *pStats)
{
    pStats->fFrameSample = 0;
    pStats->fAvgSample = 0;
    pStats->fMaxSample = 0;
}


void
Stats_AddSample (Stats *pStats, s32 frameSample)
{
    pStats->fFrameSample = frameSample;

    pStats->fAvgSample += frameSample;

    if (frameSample > pStats->fMaxSample)
	pStats->fMaxSample = frameSample;

    Hist_SetValue (&pStats->fHist, frameSample);
}


void
Stats_Draw (Stats *pStats, Rect *pRect, Gfx **ppGfx)
{
    s32 val, rectHeight;
    u16 shortcolor;
    
    /* Draw the histogram. */
    Hist_Draw (&pStats->fHist, pRect, ppGfx);

    
    /* Set up the display list commands. */
    gDPPipeSync((*ppGfx)++);
    gDPSetCycleType ((*ppGfx)++, G_CYC_FILL);
    gDPSetRenderMode ((*ppGfx)++, G_RM_OPA_SURF, G_RM_OPA_SURF2);

    /* Fill in the rectangle with gray. */
    shortcolor = GPACK_RGBA5551(22, 39, 197, 1);
    gDPSetFillColor((*ppGfx)++, shortcolor << 16 | shortcolor);
    
    /* Draw the maximum value bar. */
    rectHeight = pRect->bottom - pRect->top;
    val = (pStats->fMaxSample * rectHeight)/pStats->fLimit;
    if (val > rectHeight)
        val = rectHeight;
    
    gDPFillRectangle((*ppGfx)++, pRect->left, pRect->bottom-val, pRect->right, pRect->bottom-val);
}



/*

  Performance UI Procs

*/


static void
__PerfPaneDrawProc (UIPane *pPane, Gfx **ppGfx)
{
    UIItem *    pItem;
    int         i;
    
    /* Update the performance measurements for the audio voices. */
    Stats_AddSample (&sPerformance.fVoxStats, Seq_GetNumVoices ());

    
    /* Draw the performance window. */
    DrawBeveledRect (&pPane->bounds, FALSE, FALSE, ppGfx);
    
    
    /* Draw the performance pane's UI items. */
    for (i=0; i<pPane->numItems; i++)
    {
        pItem = &pPane->itemList[i];

        pItem->DrawProc (pItem, ppGfx);
    }
}



static void
__PerfStatsDrawProc (UIItem *pItem, Gfx **ppGfx)
{
    Stats *     pStats;
    Rect        boundsRect;
    
    Item_GetScreenBounds (pItem, &boundsRect);
    
    DrawBeveledRect (&boundsRect, TRUE, FALSE, ppGfx);

    if (pItem->id == kCPUHistItemID)
        pStats = &sPerformance.fCPUStats;

    else if (pItem->id == kRSPHistItemID)
	pStats = &sPerformance.fRSPStats;

    else if (pItem->id == kVoxHistItemID)
        pStats = &sPerformance.fVoxStats;


    InsetRect (&boundsRect, 1, 1);              /* Draw the histogram inside the frame. */
    Stats_Draw (pStats, &boundsRect, ppGfx);
}


static char
__PerfHandleEventProc (UIPane *pPane, UIEvent *pEvent)
{
    char isHandled = FALSE;

    switch (pEvent->type)
    {
      case kMouseDown:
          isHandled = __PerfHandleMouseDown (pPane, &pEvent->where);
          break;

      case kMouseUp:
          isHandled = __PerfHandleMouseUp (pPane, &pEvent->where);
          break;

      case kButtonDown:
          isHandled = __PerfHandleButtonDown (pPane, pEvent->what);
          break;
    }

    return isHandled;
}


static char
__PerfHandleMouseDown (UIPane *pPane, Point *pPt)
{
    UIItem *    pItem;
    char	isHandled = FALSE;
    
    if (Pane_ItemClicked (pPane, pPt, &pItem))
    {
        assert(pItem != NULL);

        switch (pItem->id)
        {
          case kCPUHistItemID:
              Stats_Clear (&sPerformance.fCPUStats);
              break;

          case kRSPHistItemID:
              Stats_Clear (&sPerformance.fRSPStats);
              break;

          case kVoxHistItemID:
              Stats_Clear (&sPerformance.fVoxStats);
              break;
        }
        isHandled = TRUE;
    }

    return isHandled;
}


static char
__PerfHandleMouseUp (UIPane *pPane, Point *pPt)
{
    UIItem *    pItem;
    char	isHandled = FALSE;

    if (Pane_ItemClicked (pPane, pPt, &pItem))
    {
        assert(pItem != NULL);

	isHandled = TRUE;
    }

    return isHandled;
}


static char
__PerfHandleButtonDown (UIPane *pPane, int button)
{
    return FALSE;
}