123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- #include "BFApp.h"
- #include "BFWindow.h"
- #include "gfx/RenderDevice.h"
- #include "FileStream.h"
- #include "util/BSpline.h"
- #include "util/PerfTimer.h"
- #include "sound/WwiseSound.h"
- #include "util/AllocDebug.h"
- #pragma warning(disable:4996)
- USING_NS_BF;
- BFApp* Beefy::gBFApp = NULL;
- BFApp::BFApp()
- {
- mTitle = "Beefy Application";
- mRefreshRate = 60;
- mLastProcessTick = BFTickCount();
- mFrameTimeAcc = 0;
- mDrawEnabled = true;
-
- mUpdateFunc = NULL;
- mDrawFunc = NULL;
-
- gBFApp = this;
- mSysDialogCnt = 0;
- mCursor = CURSOR_POINTER;
- mInProcess = false;
- mUpdateCnt = 0;
- mNumPhysUpdates = 0;
- mVSynched = true;
- mMaxUpdatesPerDraw = 60; // 8?
-
- mUpdateSampleCount = 0;
- mUpdateSampleTimes = 0;
- if (gPerfManager == NULL)
- gPerfManager = new PerfManager();
- mRunning = false;
- mRenderDevice = NULL;
- mVSynched = false;
- }
- BFApp::~BFApp()
- {
- gBFApp = NULL;
- delete gPerfManager;
- for (auto window : mPendingWindowDeleteList)
- delete window;
- }
- void BFApp::Init()
- {
- }
- void BFApp::Run()
- {
- }
- void BFApp::Shutdown()
- {
- mRunning = false;
- }
- void BFApp::SetCursor(int cursor)
- {
- mCursor = cursor;
- PhysSetCursor();
- }
- void BFApp::Update(bool batchStart)
- {
- //Beefy::DebugTimeGuard suspendTimeGuard(30, "BFApp::Update");
- #ifdef BF_WWISE_ENABLED
- WWiseUpdate();
- #endif
-
- mUpdateCnt++;
- gPerfManager->NextFrame();
- gPerfManager->ZoneStart("BFApp::Update");
- mUpdateFunc(batchStart);
- gPerfManager->ZoneEnd();
- for (auto window : mPendingWindowDeleteList)
- delete window;
- mPendingWindowDeleteList.clear();
- }
- void BFApp::Draw()
- {
- gPerfManager->ZoneStart("BFApp::Draw");
- mDrawFunc();
- gPerfManager->ZoneEnd();
- }
- //#define PERIODIC_PERF_TIMING
- void BFApp::Process()
- {
- //Beefy::DebugTimeGuard suspendTimeGuard(30, "BFApp::Process");
-
- if (mInProcess)
- return; // No reentry
- mInProcess = true;
- int updates;
-
- uint32 tickNow = BFTickCount();
- const int vSyncTestingPeriod = 250;
- if (mRefreshRate != 0)
- {
- float ticksPerFrame = 1000.0f / mRefreshRate;
- int ticksSinceLastProcess = tickNow - mLastProcessTick;
- mUpdateSampleCount++;
- mUpdateSampleTimes += ticksSinceLastProcess;
- //TODO: Turn off mVSynched based on error calculations - (?)
- // Two VSync failures in a row means we set mVSyncFailed and permanently disable it
- if (mUpdateSampleTimes >= vSyncTestingPeriod)
- {
- int expectedFrames = (int)(mUpdateSampleTimes / ticksPerFrame);
- if (mUpdateSampleCount > expectedFrames * 1.5)
- {
- if (!mVSynched)
- mVSyncFailed = true;
- mVSynched = false;
- }
- else
- if (!mVSyncFailed)
- mVSynched = true;
-
- mUpdateSampleCount = 0;
- mUpdateSampleTimes = 0;
- }
-
- mFrameTimeAcc += tickNow - mLastProcessTick;
-
- bool vSynched = mVSynched;
- if (vSynched)
- {
- // For the startup, try not to go hyper during those first samplings
- if (mUpdateSampleTimes <= vSyncTestingPeriod)
- {
- if (ticksSinceLastProcess < ticksPerFrame / 1.5)
- vSynched = false;
- }
- }
- if (vSynched)
- {
- updates = std::max(1, (int)(mFrameTimeAcc / ticksPerFrame + 0.5f));
- mFrameTimeAcc = std::max(0.0f, mFrameTimeAcc - ticksPerFrame * updates);
- }
- else
- {
- updates = std::max(0, (int)(mFrameTimeAcc / ticksPerFrame));
- mFrameTimeAcc = mFrameTimeAcc - ticksPerFrame * updates;
- }
-
- if (updates > mRefreshRate)
- {
- // If more than 1 second of updates is queued, just re-sync
- updates = 1;
- mFrameTimeAcc = 0;
- }
- // Compensate for "slow start" by limiting the number of catchup-updates we can do when starting the app
- int maxUpdates = BF_MIN(mNumPhysUpdates + 1, mMaxUpdatesPerDraw);
- updates = BF_MIN(updates, maxUpdates);
-
- /*if (updates > 2)
- OutputDebugStrF("Updates: %d TickDelta: %d\n", updates, tickNow - mLastProcessTick);*/
- }
- else
- updates = 1; // RefreshRate of 0 means to update as fast as possible
-
- if (updates == 0)
- {
- // Yield
- BfpThread_Sleep(1);
- }
-
- static uint32 lastUpdate = BFTickCount();
-
- #ifdef PERIODIC_PERF_TIMING
- bool perfTime = (tickNow - lastUpdate >= 5000) && (updates > 0);
- if (perfTime)
- {
- updates = 1;
- lastUpdate = tickNow;
-
- if (perfTime)
- gPerfManager->StartRecording();
- }
- #endif
- if (updates > 0)
- mNumPhysUpdates++;
- for (int updateNum = 0; updateNum < updates; updateNum++)
- {
- if (!mRunning)
- break;
- Update(updateNum == 0);
- }
-
- if ((mRunning) && (updates > 0))
- Draw();
- #ifdef PERIODIC_PERF_TIMING
- if (perfTime)
- {
- gPerfManager->StopRecording();
- gPerfManager->DbgPrint();
- }
- #endif
- mLastProcessTick = tickNow;
- mInProcess = false;
- }
- void BFApp::RemoveWindow(BFWindow* window)
- {
- auto itr = std::find(mWindowList.begin(), mWindowList.end(), window);
- if (itr == mWindowList.end()) // Allow benign failure (double removal)
- return;
- mWindowList.erase(itr);
- while (window->mChildren.size() > 0)
- RemoveWindow(window->mChildren.front());
- if (window->mParent != NULL)
- {
- window->mParent->mChildren.erase(std::find(window->mParent->mChildren.begin(), window->mParent->mChildren.end(), window));
- if (window->mFlags & BFWINDOW_MODAL)
- {
- bool hasModal = false;
- for (auto childWindow : window->mParent->mChildren)
- {
- if (childWindow->mFlags & BFWINDOW_MODAL)
- hasModal = true;
- }
- if (!hasModal)
- window->mParent->ModalsRemoved();
- }
- }
- window->mClosedFunc(window);
- mRenderDevice->RemoveRenderWindow(window->mRenderWindow);
- window->Destroy();
- mPendingWindowDeleteList.push_back(window);
- }
- FileStream* BFApp::OpenBinaryFile(const StringImpl& fileName)
- {
- FILE* fP = fopen(fileName.c_str(), "rb");
- if (fP == NULL)
- return NULL;
- FileStream* fileStream = new FileStream();
- fileStream->mFP = fP;
- return fileStream;
- }
|