Archival snapshot of the Virtual World Entertainment Tesla cockpit software, 1994-1996: MUNGA engine and L4 pod layer source (Borland C++ 5.0), BT/RP game code, and game content (models, audio, maps, gauges, Division renderer data). Includes third-party libraries: Division dVS/DPL graphics, HMI SOS audio, WATTCP networking. Files are preserved byte-for-byte (.gitattributes disables all line-ending conversion). README.md documents the layout, target hardware, and toolchain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
485 lines
16 KiB
C++
485 lines
16 KiB
C++
//===========================================================================//
|
|
// File: l4vidper.cpp //
|
|
// Project: MUNGA Brick: Video Renderer Manager //
|
|
// Contents: Interface specification Video performance monitoring tools //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 03/5/96 GAC initial coding //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "l4munga.hpp"
|
|
#if !defined(L4VIDPER_HPP)
|
|
# include "l4vidper.hpp"
|
|
#endif
|
|
|
|
extern "C" const int32 __sect_time;
|
|
extern "C" const int32 __last_cull_time;
|
|
extern "C" const int32 __last_draw_time;
|
|
extern "C" const int32 __last_frame_time;
|
|
extern "C" const int32 __last_pxpl_time;
|
|
extern "C" const int32 __last_frame_prims;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the StripChartRenderable
|
|
// Used to performance monitor a variable that can change every frame
|
|
//
|
|
StripChartRenderable::StripChartRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_VIEW *this_view, // the view associated with our eye
|
|
float left,
|
|
float right,
|
|
float top,
|
|
float bottom,
|
|
int max_samples, // The number of samples to hold
|
|
int max_value, // The maximum value allowed
|
|
int min_value, // the minimum value allowed
|
|
int *value_to_chart, // the value we will be graphing
|
|
int update_interval // How frequently (in frames) to update the graphics
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
int
|
|
i;
|
|
//
|
|
// Save the incoming data inside this class
|
|
//
|
|
myView = this_view;
|
|
myLeft = left;
|
|
myRight = right;
|
|
myTop = top;
|
|
myBottom = bottom;
|
|
myMaxSamples = max_samples;
|
|
myMaxValue = max_value;
|
|
myMinValue = min_value;
|
|
myValue = value_to_chart;
|
|
myUpdateInterval = update_interval;
|
|
myFrameCount = 0;
|
|
myCurrentSample = 0;
|
|
//
|
|
// Allocate the RAM to store the values we are charting and clear them out
|
|
//
|
|
myValueStorage = new int[max_samples];
|
|
if(!myValueStorage)
|
|
Fail("stripchart couldn't allocate value storage\n");
|
|
|
|
Check_Pointer(myValueStorage);
|
|
for(i = 0; i<max_samples; i++)
|
|
{
|
|
myValueStorage[i] = 0;
|
|
}
|
|
//
|
|
// Allocate space for the display list
|
|
//
|
|
myDisplayList = dpl2d_NewDisplayList();
|
|
if(!myDisplayList)
|
|
Fail("stripchart couldn't allocate a display list\n");
|
|
//
|
|
// Draw the bounding box for the chart
|
|
//
|
|
dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear);
|
|
dpl2d_AddFullScreenClipRegion (myDisplayList);
|
|
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
|
|
dpl2d_AddPoint (myDisplayList, myRight, myBottom);
|
|
dpl2d_AddPoint (myDisplayList, myRight, myTop);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myTop);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
dpl2d_CloseDisplayList (myDisplayList);
|
|
dpl2d_FlushDisplayList (myDisplayList);
|
|
//
|
|
// Bind the chart to our eyepoint
|
|
//
|
|
dpl2d_SetViewDisplayList ( myView, myDisplayList );
|
|
dpl_FlushView ( myView );
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for the StripChartRenderable
|
|
//
|
|
StripChartRenderable::~StripChartRenderable()
|
|
{
|
|
//
|
|
// Make sure our structure is still in one piece
|
|
//
|
|
Check(this);
|
|
//
|
|
// Unhook the display list from the view, then delete both lists
|
|
//
|
|
dpl2d_SetViewDisplayList ( myView, NULL );
|
|
dpl_FlushView ( myView );
|
|
dpl2d_DeleteDisplayList(myDisplayList);
|
|
delete myValueStorage;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the StripChartRenderable
|
|
//
|
|
Logical
|
|
StripChartRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the StripChartRenderable
|
|
//
|
|
void
|
|
StripChartRenderable::Execute()
|
|
{
|
|
int
|
|
i;
|
|
//
|
|
// Increment frame counter
|
|
//
|
|
myFrameCount++;
|
|
//
|
|
// Grab the statistic we're tracking and stuff it into the buffer
|
|
//
|
|
myValueStorage[myCurrentSample] = *myValue;
|
|
//
|
|
// If it's time to redraw the graph, do it
|
|
//
|
|
if(myFrameCount >= myUpdateInterval)
|
|
{
|
|
myFrameCount = 0;
|
|
//
|
|
// Figure the scale factor for the graph
|
|
//
|
|
float
|
|
current_x,
|
|
current_y,
|
|
x_increment,
|
|
y_increment;
|
|
x_increment = (myRight - myLeft)/ (float)(myMaxSamples);
|
|
y_increment = (myBottom - myTop)/((float)myMaxValue - (float)myMinValue);
|
|
dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear);
|
|
dpl2d_AddFullScreenClipRegion (myDisplayList);
|
|
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
|
|
dpl2d_AddPoint (myDisplayList, myRight, myBottom);
|
|
dpl2d_AddPoint (myDisplayList, myRight, myTop);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myTop);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
current_x = myLeft;
|
|
for(i = 0; i < myMaxSamples; i++)
|
|
{
|
|
current_y = myBottom-((float)myValueStorage[i] * y_increment);
|
|
dpl2d_AddPoint(myDisplayList,current_x,current_y);
|
|
current_x += x_increment;
|
|
}
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
dpl2d_AddOpenLines (myDisplayList);
|
|
dpl2d_AddPoint (myDisplayList,
|
|
myLeft + (x_increment*myCurrentSample),
|
|
myBottom);
|
|
dpl2d_AddPoint (myDisplayList,
|
|
myLeft + (x_increment*myCurrentSample),
|
|
myTop);
|
|
dpl2d_AddCloseLines (myDisplayList);
|
|
dpl2d_CloseDisplayList (myDisplayList);
|
|
dpl2d_FlushDisplayList (myDisplayList);
|
|
}
|
|
//
|
|
// Update the current sample pointer
|
|
//
|
|
myCurrentSample ++;
|
|
if(myCurrentSample >= myMaxSamples)
|
|
myCurrentSample = 0;
|
|
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
VideoRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the RendererChartRenderable
|
|
// Used to performance monitor a variable that can change every frame
|
|
//
|
|
RendererChartRenderable::RendererChartRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_VIEW *this_view, // the view associated with our eye
|
|
float left,
|
|
float right,
|
|
float top,
|
|
float bottom,
|
|
int max_samples, // The number of samples to hold
|
|
int max_value, // The maximum value allowed
|
|
int min_value, // the minimum value allowed
|
|
int update_interval // How frequently (in frames) to update the graphics
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
int
|
|
i;
|
|
//
|
|
// Save the incoming data inside this class
|
|
//
|
|
myView = this_view;
|
|
myLeft = left;
|
|
myRight = right;
|
|
myTop = top;
|
|
myBottom = bottom;
|
|
myMaxSamples = max_samples;
|
|
myMaxValue = max_value;
|
|
myMinValue = min_value;
|
|
myUpdateInterval = update_interval;
|
|
myFrameCount = 0;
|
|
myCurrentSample = 0;
|
|
//
|
|
// Allocate the RAM to store the values we are charting and clear them out
|
|
//
|
|
myCullStorage = new int[max_samples];
|
|
myDrawStorage = new int[max_samples];
|
|
myFrameStorage = new int[max_samples];
|
|
myPixelPlanesStorage = new int[max_samples];
|
|
myPrimativeStorage = new int[max_samples];
|
|
if(!myCullStorage || !myDrawStorage || !myFrameStorage || !myPixelPlanesStorage || !myPrimativeStorage)
|
|
Fail("RendererChartRenderable couldn't allocate storage\n");
|
|
|
|
Check_Pointer(myValueStorage);
|
|
for(i = 0; i<max_samples; i++)
|
|
{
|
|
myCullStorage[i] = 0;
|
|
myDrawStorage[i] = 0;
|
|
myFrameStorage[i] = 0;
|
|
myPixelPlanesStorage[i] = 0;
|
|
myPrimativeStorage[i] = 0;
|
|
}
|
|
//
|
|
// Allocate space for the display list
|
|
//
|
|
myDisplayList = dpl2d_NewDisplayList();
|
|
if(!myDisplayList)
|
|
Fail("stripchart couldn't allocate a display list\n");
|
|
//
|
|
// Draw the bounding box for the chart
|
|
//
|
|
dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear);
|
|
dpl2d_AddFullScreenClipRegion (myDisplayList);
|
|
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
|
|
dpl2d_AddSetLineWidth (myDisplayList,1.0);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
|
|
dpl2d_AddPoint (myDisplayList, myRight, myBottom);
|
|
dpl2d_AddPoint (myDisplayList, myRight, myTop);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myTop);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
//
|
|
// Bind the chart to our eyepoint
|
|
//
|
|
mySystemDisplayList = dpl2d_GetViewDisplayList (myView);
|
|
if(mySystemDisplayList)
|
|
{
|
|
// If a display list was already installed, call it at the end of this
|
|
// 2d display list so it will still show up. (ugley, but as this is
|
|
// test code only it should be sufficient)
|
|
dpl2d_AddCallDisplayList (myDisplayList, mySystemDisplayList );
|
|
|
|
}
|
|
dpl2d_CloseDisplayList (myDisplayList);
|
|
dpl2d_FlushDisplayList (myDisplayList);
|
|
//
|
|
// hook our dlist up to the view so it will be drawn
|
|
//
|
|
dpl2d_SetViewDisplayList ( myView, myDisplayList );
|
|
dpl_FlushView ( myView );
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for the RendererChartRenderable
|
|
//
|
|
RendererChartRenderable::~RendererChartRenderable()
|
|
{
|
|
//
|
|
// Make sure our structure is still in one piece
|
|
//
|
|
Check(this);
|
|
//
|
|
// Unhook the display list from the view, then delete both lists
|
|
//
|
|
dpl2d_SetViewDisplayList ( myView, NULL );
|
|
dpl_FlushView ( myView );
|
|
dpl2d_DeleteDisplayList(myDisplayList);
|
|
delete myCullStorage;
|
|
delete myDrawStorage;
|
|
delete myFrameStorage;
|
|
delete myPixelPlanesStorage;
|
|
delete myPrimativeStorage;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the RendererChartRenderable
|
|
//
|
|
Logical
|
|
RendererChartRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the RendererChartRenderable
|
|
//
|
|
void
|
|
RendererChartRenderable::Execute()
|
|
{
|
|
int
|
|
i;
|
|
//
|
|
// Increment frame counter
|
|
//
|
|
myFrameCount++;
|
|
//
|
|
// Grab the statistic we're tracking and stuff it into the buffer
|
|
//
|
|
myCullStorage[myCurrentSample] = __last_cull_time;
|
|
myDrawStorage[myCurrentSample] = __last_draw_time;
|
|
myFrameStorage[myCurrentSample] = __last_frame_time;
|
|
myPixelPlanesStorage[myCurrentSample] = __last_pxpl_time;
|
|
myPrimativeStorage[myCurrentSample] = __last_frame_prims;
|
|
//
|
|
// If it's time to redraw the graph, do it
|
|
//
|
|
if(myFrameCount >= myUpdateInterval)
|
|
{
|
|
myFrameCount = 0;
|
|
//
|
|
// Figure the scale factor for the graph
|
|
//
|
|
float
|
|
current_x,
|
|
current_y,
|
|
x_increment,
|
|
y_increment;
|
|
x_increment = (myRight - myLeft)/ (float)(myMaxSamples);
|
|
y_increment = (myBottom - myTop)/((float)myMaxValue - (float)myMinValue);
|
|
dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear);
|
|
dpl2d_AddFullScreenClipRegion (myDisplayList);
|
|
dpl2d_AddSetLineWidth (myDisplayList,1.0);
|
|
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
|
|
dpl2d_AddPoint (myDisplayList, myRight, myBottom);
|
|
dpl2d_AddPoint (myDisplayList, myRight, myTop);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myTop);
|
|
dpl2d_AddPoint (myDisplayList, myLeft, myBottom);
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
//
|
|
// Draw the primative count trace
|
|
//
|
|
dpl2d_AddOpenLines (myDisplayList);
|
|
dpl2d_AddPoint(myDisplayList,myLeft, myBottom + (500.0f * y_increment * 50.0f));
|
|
dpl2d_AddPoint(myDisplayList,myRight, myBottom + (500.0f * y_increment * 50.0f));
|
|
dpl2d_AddPoint(myDisplayList,myLeft, myBottom + (1000.0f * y_increment * 50.0f));
|
|
dpl2d_AddPoint(myDisplayList,myRight, myBottom + (1000.0f * y_increment * 50.0f));
|
|
dpl2d_AddCloseLines (myDisplayList);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
current_x = myLeft;
|
|
for(i = 0; i < myMaxSamples; i++)
|
|
{
|
|
current_y = myBottom+((float)myPrimativeStorage[i] * y_increment * 50.0f);
|
|
dpl2d_AddPoint(myDisplayList,current_x,current_y);
|
|
current_x += x_increment;
|
|
}
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
//
|
|
// Draw the frame time trace
|
|
//
|
|
dpl2d_AddSetColor (myDisplayList, 0.75f, 0.75f, 0.75f);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
current_x = myLeft;
|
|
for(i = 0; i < myMaxSamples; i++)
|
|
{
|
|
current_y = myBottom-((float)myFrameStorage[i] * y_increment);
|
|
dpl2d_AddPoint(myDisplayList,current_x,current_y);
|
|
current_x += x_increment;
|
|
}
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
//
|
|
// Draw the draw time trace
|
|
//
|
|
dpl2d_AddSetColor (myDisplayList, 0.75f, 0.0f, 0.0f);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
current_x = myLeft;
|
|
for(i = 0; i < myMaxSamples; i++)
|
|
{
|
|
current_y = myBottom-((float)myDrawStorage[i] * y_increment);
|
|
dpl2d_AddPoint(myDisplayList,current_x,current_y);
|
|
current_x += x_increment;
|
|
}
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
//
|
|
// Draw the pixel planes time trace
|
|
//
|
|
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.0f, 0.75f);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
current_x = myLeft;
|
|
for(i = 0; i < myMaxSamples; i++)
|
|
{
|
|
current_y = myBottom-((float)myPixelPlanesStorage[i] * y_increment);
|
|
dpl2d_AddPoint(myDisplayList,current_x,current_y);
|
|
current_x += x_increment;
|
|
}
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
//
|
|
// Stack the cull time on top of the draw
|
|
//
|
|
dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f);
|
|
dpl2d_AddOpenPolyline (myDisplayList);
|
|
current_x = myLeft;
|
|
for(i = 0; i < myMaxSamples; i++)
|
|
{
|
|
current_y = myBottom-(((float)myCullStorage[i] + (float)myDrawStorage[i]) * y_increment);
|
|
dpl2d_AddPoint(myDisplayList,current_x,current_y);
|
|
current_x += x_increment;
|
|
}
|
|
dpl2d_AddClosePolyline (myDisplayList);
|
|
//
|
|
// Draw a line indicating the current time
|
|
//
|
|
dpl2d_AddOpenLines (myDisplayList);
|
|
dpl2d_AddPoint (myDisplayList,
|
|
myLeft + (x_increment*myCurrentSample),
|
|
myBottom);
|
|
dpl2d_AddPoint (myDisplayList,
|
|
myLeft + (x_increment*myCurrentSample),
|
|
myTop);
|
|
dpl2d_AddCloseLines (myDisplayList);
|
|
//
|
|
// If there is a pre existing dlist, insert a call to it here
|
|
//
|
|
if(mySystemDisplayList)
|
|
{
|
|
dpl2d_AddCallDisplayList (myDisplayList, mySystemDisplayList );
|
|
}
|
|
//
|
|
// Close up the display list and flush it
|
|
//
|
|
dpl2d_CloseDisplayList (myDisplayList);
|
|
dpl2d_FlushDisplayList (myDisplayList);
|
|
}
|
|
//
|
|
// Update the current sample pointer
|
|
//
|
|
myCurrentSample ++;
|
|
if(myCurrentSample >= myMaxSamples)
|
|
myCurrentSample = 0;
|
|
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
VideoRenderable::Execute();
|
|
}
|