123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- #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();
- mPhysFrameTimeAcc = 0;
- mDrawEnabled = true;
-
- mUpdateFunc = NULL;
- mUpdateFFunc = 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;
- mVSyncActive = false;
- mForceNextDraw = false;
- mUpdateCnt = 0;
- mUpdateCntF = 0;
- mClientUpdateCntF = 0;
- }
- 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::UpdateF(float updatePct)
- {
- mUpdateFFunc(updatePct);
- }
- void BFApp::Draw()
- {
- gPerfManager->ZoneStart("BFApp::Draw");
- mDrawFunc(mForceNextDraw);
- mForceNextDraw = false;
- gPerfManager->ZoneEnd();
- }
- //#define PERIODIC_PERF_TIMING
- void BFApp::Process()
- {
- //Beefy::DebugTimeGuard suspendTimeGuard(30, "BFApp::Process");
-
- RenderWindow* headRenderWindow = NULL;
- float physRefreshRate = 0;
- if ((mRenderDevice != NULL) && (!mRenderDevice->mRenderWindowList.IsEmpty()))
- {
- headRenderWindow = mRenderDevice->mRenderWindowList[0];
- physRefreshRate = headRenderWindow->GetRefreshRate();
- }
- if (physRefreshRate <= 0)
- physRefreshRate = 60.0f;
- float ticksPerFrame = 1;
- float physTicksPerFrame = 1000.0f / physRefreshRate;
- if (mInProcess)
- return; // No reentry
- mInProcess = true;
-
- uint32 tickNow = BFTickCount();
- const int vSyncTestingPeriod = 250;
-
- bool didVBlankWait = false;
-
- if (mVSyncActive)
- {
- // Have a time limit in the cases we miss the vblank
- if (mVSyncEvent.WaitFor((int)(physTicksPerFrame + 1)))
- didVBlankWait = true;
- }
- if (mRefreshRate > 0)
- 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;
- }
-
- mPhysFrameTimeAcc += tickNow - mLastProcessTick;
-
- if (didVBlankWait)
- {
- // Try to keep time synced with vblank
- if (mPhysFrameTimeAcc < physTicksPerFrame * 2)
- {
- float timeAdjust = physTicksPerFrame - mPhysFrameTimeAcc + 0.001f;
- mPhysFrameTimeAcc += timeAdjust;
- }
- }
- /*if (updates > 2)
- OutputDebugStrF("Updates: %d TickDelta: %d\n", updates, tickNow - mLastProcessTick);*/
-
- // 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);
- while (mPhysFrameTimeAcc >= physTicksPerFrame)
- {
- mPhysFrameTimeAcc -= physTicksPerFrame;
- mUpdateCntF += physTicksPerFrame / ticksPerFrame;
- }
-
- 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
-
- int didUpdateCnt = 0;
-
- if (mUpdateCntF - mClientUpdateCntF > physRefreshRate / 2)
- {
- // Too large of a difference, just sync
- mClientUpdateCntF = mUpdateCntF - 1;
- }
- while ((mRunning) && ((int)mClientUpdateCntF < (int)mUpdateCntF))
- {
- Update(didUpdateCnt == 0);
- didUpdateCnt++;
- mClientUpdateCntF = (int)mClientUpdateCntF + 1.000001;
- if (didUpdateCnt >= maxUpdates)
- break;
- }
- // Only attempt UpdateF updates if our rates aren't nearly the same
- if ((mRunning) && (mRefreshRate != 0) && (fabs(physRefreshRate - mRefreshRate) / (float)mRefreshRate > 0.1f))
- {
- float updateFAmt = (float)(mUpdateCntF - mClientUpdateCntF);
- if ((updateFAmt > 0.05f) && (updateFAmt < 1.0f) && (didUpdateCnt < maxUpdates))
- {
- UpdateF(updateFAmt);
- didUpdateCnt++;
- mClientUpdateCntF = mUpdateCntF;
- }
- }
- if (didUpdateCnt > 0)
- mNumPhysUpdates++;
- if ((mRunning) && (didUpdateCnt == 0))
- {
- BfpThread_Sleep(1);
- }
-
- if ((mRunning) &&
- ((didUpdateCnt != 0) || (mForceNextDraw)))
- Draw();
- #ifdef PERIODIC_PERF_TIMING
- if (perfTime)
- {
- gPerfManager->StopRecording();
- gPerfManager->DbgPrint();
- }
- #endif
- mLastProcessTick = tickNow;
- mInProcess = false;
- }
- void BFApp::RemoveWindow(BFWindow* window)
- {
- AutoCrit autoCrit(mCritSect);
- 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;
- }
|