From 2942e011bfdc7c485a68432c9a36614e3c0c9680 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 16 Apr 2021 21:27:54 +0200 Subject: [PATCH] - cleaned up the screen job's fade handling, now that the jobs no longer depend on an external timer. --- source/common/2d/v_2ddrawer.cpp | 3 +- source/common/2d/v_2ddrawer.h | 4 +- .../common/rendering/hwrenderer/hw_draw2d.cpp | 2 +- source/core/screenjob.cpp | 102 +++++++----------- source/core/screenjob.h | 13 +-- source/games/duke/src/2d_d.cpp | 2 +- 6 files changed, 46 insertions(+), 80 deletions(-) diff --git a/source/common/2d/v_2ddrawer.cpp b/source/common/2d/v_2ddrawer.cpp index d774d12b4..911c5d7ee 100644 --- a/source/common/2d/v_2ddrawer.cpp +++ b/source/common/2d/v_2ddrawer.cpp @@ -189,8 +189,9 @@ DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, PushTriangle, Shape2D_PushTriangle) // //========================================================================== -int F2DDrawer::AddCommand(const RenderCommand *data) +int F2DDrawer::AddCommand(RenderCommand *data) { + data->mScreenFade = screenFade; if (mData.Size() > 0 && data->isCompatible(mData.Last())) { // Merge with the last command. diff --git a/source/common/2d/v_2ddrawer.h b/source/common/2d/v_2ddrawer.h index d1c2a161e..b3e7d2aa5 100644 --- a/source/common/2d/v_2ddrawer.h +++ b/source/common/2d/v_2ddrawer.h @@ -118,6 +118,7 @@ public: ETexMode mDrawMode; uint8_t mLightLevel; uint8_t mFlags; + float mScreenFade; bool useTransform; DMatrix3x3 transform; @@ -149,6 +150,7 @@ public: mLightLevel == other.mLightLevel && mColor1.d == other.mColor1.d && useTransform == other.useTransform && + mScreenFade == other.mScreenFade && ( !useTransform || ( @@ -172,7 +174,7 @@ public: int fullscreenautoaspect = 3; int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1; - int AddCommand(const RenderCommand *data); + int AddCommand(RenderCommand *data); void AddIndices(int firstvert, int count, ...); private: void AddIndices(int firstvert, TArray &v); diff --git a/source/common/rendering/hwrenderer/hw_draw2d.cpp b/source/common/rendering/hwrenderer/hw_draw2d.cpp index 36fd8f369..cf3399432 100644 --- a/source/common/rendering/hwrenderer/hw_draw2d.cpp +++ b/source/common/rendering/hwrenderer/hw_draw2d.cpp @@ -85,7 +85,6 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state) vb.UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size()); state.SetVertexBuffer(&vb); state.EnableFog(false); - state.SetScreenFade(drawer->screenFade); for(auto &cmd : commands) { @@ -94,6 +93,7 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state) state.SetRenderStyle(cmd.mRenderStyle); state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed)); state.EnableFog(2); // Special 2D mode 'fog'. + state.SetScreenFade(cmd.mScreenFade); state.SetTextureMode(cmd.mDrawMode); diff --git a/source/core/screenjob.cpp b/source/core/screenjob.cpp index 6f7b53436..14bcc86ea 100644 --- a/source/core/screenjob.cpp +++ b/source/core/screenjob.cpp @@ -125,11 +125,10 @@ class ScreenJobRunner int index = -1; float screenfade; bool clearbefore; - int64_t startTime = -1; - int64_t lastTime = -1; int actionState; int terminateState; - uint64_t clock = 0; + int fadeticks = 0; + int last_M_Active_Tic = -1; public: ScreenJobRunner(JobDesc* jobs_, int count, CompletionFunc completion_, bool clearbefore_) @@ -174,73 +173,39 @@ public: index++; } actionState = clearbefore ? State_Clear : State_Run; - if (index < jobs.Size()) screenfade = jobs[index].job->fadestyle & DScreenJob::fadein ? 0.f : 1.f; - lastTime= startTime = -1; - clock = 0; + if (index < jobs.Size()) + { + jobs[index].job->fadestate = jobs[index].job->fadestyle & DScreenJob::fadein? DScreenJob::fadein : DScreenJob::visible; + } inputState.ClearAllInput(); } - int DisplayFrame() + int DisplayFrame(double smoothratio) { auto& job = jobs[index]; auto now = I_GetTimeNS(); bool processed = job.job->ProcessInput(); - if (startTime == -1) - { - lastTime = startTime = now; - } - else if (!M_Active()) - { - clock += now - lastTime; - if (clock == 0) clock = 1; - } - bool skiprequest = clock > 100'000'000 && inputState.CheckAllInput() && !processed && job.job->fadestate != DScreenJob::fadeout; - lastTime = now; - if (screenfade < 1.f && !M_Active()) + if (job.job->fadestate == DScreenJob::fadein) { - float ms = (clock / 1'000'000) / job.job->fadetime; - screenfade = clamp(ms, 0.f, 1.f); + double ms = (job.job->ticks + smoothratio) * 1000 / GameTicRate / job.job->fadetime; + float screenfade = (float)clamp(ms, 0., 1.); twod->SetScreenFade(screenfade); - if (job.job->fadestate != DScreenJob::fadeout) - job.job->fadestate = DScreenJob::fadein; + if (screenfade == 1.f) job.job->fadestate = DScreenJob::visible; } - else - { - job.job->fadestate = DScreenJob::visible; - screenfade = 1.f; - } - job.job->SetClock(clock); - int state = job.job->Frame(clock, skiprequest, M_Active()? 1. : I_GetTimeFrac()); - clock = job.job->GetClock(); - if (clock == 0) clock = 1; + int state = job.job->DrawFrame(smoothratio); + twod->SetScreenFade(1.f); return state; } - int FadeoutFrame() + int FadeoutFrame(double smoothratio) { - auto now = I_GetTimeNS(); - - if (startTime == -1) - { - lastTime = startTime = now; - } - else if (!M_Active()) - { - clock += now - lastTime; - if (clock == 0) clock = 1; - } - lastTime = now; - - float ms = (clock / 1'000'000) / jobs[index].job->fadetime; - float screenfade2 = clamp(screenfade - ms, 0.f, 1.f); - if (!M_Active()) twod->SetScreenFade(screenfade2); - if (screenfade2 <= 0.f) - { - twod->Unlock(); // must unlock before displaying. - return 0; - } - return 1; + auto& job = jobs[index]; + double ms = (job.job->ticks + smoothratio) * 1000 / GameTicRate / job.job->fadetime; + float screenfade = 1.f - (float)clamp(ms, 0., 1.); + twod->SetScreenFade(screenfade); + job.job->DrawFrame(1.); + return (screenfade > 0.f); } bool OnEvent(event_t* ev) @@ -268,9 +233,15 @@ public: } else { - if (jobs[index].job->state != DScreenJob::running) return; - jobs[index].job->ticks++; - jobs[index].job->OnTick(); + if (jobs[index].job->state == DScreenJob::running) + { + jobs[index].job->ticks++; + jobs[index].job->OnTick(); + } + else if (jobs[index].job->state == DScreenJob::stopping) + { + fadeticks++; + } } } @@ -284,6 +255,13 @@ public: if (completion) completion(false); return false; } + + // ensure that we won't go back in time if the menu is dismissed without advancing our ticker + bool menuon = M_Active(); + if (menuon) last_M_Active_Tic = jobs[index].job->ticks; + else if (last_M_Active_Tic == jobs[index].job->ticks) menuon = true; + double smoothratio = menuon ? 1. : I_GetTimeFrac(); + if (actionState == State_Clear) { actionState = State_Run; @@ -291,18 +269,14 @@ public: } else if (actionState == State_Run) { - terminateState = DisplayFrame(); + terminateState = DisplayFrame(smoothratio); if (terminateState < 1) { // Must lock before displaying. if (jobs[index].job->fadestyle & DScreenJob::fadeout) { - twod->Lock(); - startTime = -1; - clock = 0; jobs[index].job->fadestate = DScreenJob::fadeout; jobs[index].job->state = DScreenJob::stopping; - gamestate = GS_INTRO; // block menu and console during fadeout - this can cause timing problems. actionState = State_Fadeout; } else @@ -313,7 +287,7 @@ public: } else if (actionState == State_Fadeout) { - int ended = FadeoutFrame(); + int ended = FadeoutFrame(smoothratio); if (ended < 1) { jobs[index].job->state = DScreenJob::stopped; diff --git a/source/core/screenjob.h b/source/core/screenjob.h index c500c139a..b856b07a2 100644 --- a/source/core/screenjob.h +++ b/source/core/screenjob.h @@ -11,7 +11,6 @@ class ScreenJobRunner; class DScreenJob : public DObject { DECLARE_CLASS(DScreenJob, DObject) - int64_t now; const int fadestyle; const float fadetime; // in milliseconds int fadestate = fadein; @@ -45,21 +44,11 @@ public: return false; } - void SetClock(int64_t nsnow) - { - now = nsnow; - } - - int64_t GetClock() const - { - return now; - } - virtual bool OnEvent(event_t* evt) { return false; } virtual void OnTick() { /*state = finished;*/ } virtual void Draw(double smoothratio) {} - int Frame(uint64_t clock, bool skiprequest, double smoothratio) + int DrawFrame(double smoothratio) { if (state != running) smoothratio = 1; // this is necessary because the ticker won't be incremented anymore to avoid having a negative time span. Draw(smoothratio); diff --git a/source/games/duke/src/2d_d.cpp b/source/games/duke/src/2d_d.cpp index b41789177..f5c95c74b 100644 --- a/source/games/duke/src/2d_d.cpp +++ b/source/games/duke/src/2d_d.cpp @@ -526,7 +526,7 @@ class DEpisode4Text : public DSkippableScreenJob public: DEpisode4Text() : DSkippableScreenJob(fadein | fadeout) {} - void Draw(double) + void Draw(double) override { twod->ClearScreen(); BigText(160, 60, GStrings("Thanks to all our"));