From 2ed744963ca39d1e8ca875c06606220a2d7e0d27 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 27 Mar 2018 20:02:44 +0200 Subject: [PATCH] - Changed frame buffer locking mechanism so that the only place where a lock is needed is when the software renderer wants to access the render buffer, which is precisely for the duration of the RenderView function. No more locking insanity! :) There are no locking counters or other saveguards here that would complicate the implementation because there's precisely two places where this buffer must be locked - the RenderView functions of the regular and poly SW renderer which cannot be called recursively. --- src/c_console.cpp | 19 +-------- src/c_console.h | 2 +- src/d_main.cpp | 30 +++++--------- src/gl/system/gl_swframebuffer.cpp | 64 +++++++++--------------------- src/gl/system/gl_swframebuffer.h | 4 ++ src/polyrenderer/poly_renderer.cpp | 22 +++++----- src/swrenderer/scene/r_scene.cpp | 56 ++++++++++++++------------ src/v_video.h | 30 +++++++++----- 8 files changed, 100 insertions(+), 127 deletions(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index ab0db58ff..a4630a952 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1069,7 +1069,7 @@ void C_SetTicker (unsigned int at, bool forceUpdate) TickerAt = at > TickerMax ? TickerMax : at; } -void C_DrawConsole (bool hw2d) +void C_DrawConsole () { static int oldbottom = 0; int lines, left, offset; @@ -1114,7 +1114,7 @@ void C_DrawConsole (bool hw2d) DTA_DestWidth, screen->GetWidth(), DTA_DestHeight, screen->GetHeight(), DTA_ColorOverlay, conshade, - DTA_Alpha, (hw2d && gamestate != GS_FULLCONSOLE) ? (double)con_alpha : 1., + DTA_Alpha, (gamestate != GS_FULLCONSOLE) ? (double)con_alpha : 1., DTA_Masked, false, TAG_DONE); if (conline && visheight < screen->GetHeight()) @@ -1192,21 +1192,6 @@ void C_DrawConsole (bool hw2d) } } - // Apply palette blend effects - if (StatusBar != NULL && !hw2d) - { - player_t *player = StatusBar->CPlayer; - if (player->camera != NULL && player->camera->player != NULL) - { - player = player->camera->player; - } - if (player->BlendA != 0 && (gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL)) - { - screen->Dim (PalEntry ((unsigned char)(player->BlendR*255), (unsigned char)(player->BlendG*255), (unsigned char)(player->BlendB*255)), - player->BlendA, 0, ConBottom, screen->GetWidth(), screen->GetHeight() - ConBottom); - V_SetBorderNeedRefresh(); - } - } } if (menuactive != MENU_Off) diff --git a/src/c_console.h b/src/c_console.h index f88af4175..9e563b3ef 100644 --- a/src/c_console.h +++ b/src/c_console.h @@ -67,7 +67,7 @@ void AddToConsole (int printlevel, const char *string); int PrintString (int printlevel, const char *string); int VPrintf (int printlevel, const char *format, va_list parms) GCCFORMAT(2); -void C_DrawConsole (bool hw2d); +void C_DrawConsole (); void C_ToggleConsole (void); void C_FullConsole (void); void C_HideConsole (void); diff --git a/src/d_main.cpp b/src/d_main.cpp index 6002a5672..1d857a809 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -669,7 +669,6 @@ CVAR (Flag, compat_pushwindow, compatflags2, COMPATF2_PUSHWINDOW); void D_Display () { bool wipe; - bool hw2d; if (nodrawers || screen == NULL) return; // for comparative timing / profiling @@ -774,9 +773,6 @@ void D_Display () wipe = false; } - hw2d = false; - - { screen->FrameTime = I_msTimeFS(); TexMan.UpdateAnimations(screen->FrameTime); @@ -785,8 +781,8 @@ void D_Display () { case GS_FULLCONSOLE: screen->SetBlendingRect(0,0,0,0); - hw2d = screen->Begin2D(false); - C_DrawConsole (false); + screen->Begin2D(false); + C_DrawConsole (); M_Drawer (); screen->Update (); return; @@ -795,10 +791,7 @@ void D_Display () case GS_TITLELEVEL: if (!gametic) { - if (!screen->HasBegun2D()) - { - screen->Begin2D(false); - } + screen->Begin2D(false); break; } @@ -815,11 +808,8 @@ void D_Display () // Renderer->RenderView(&players[consoleplayer]); - if ((hw2d = screen->Begin2D(viewactive))) - { - // Redraw everything every frame when using 2D accel - V_SetBorderNeedRefresh(); - } + screen->Begin2D(viewactive); + V_SetBorderNeedRefresh(); Renderer->DrawRemainingPlayerSprites(); screen->DrawBlendingRect(); if (automapactive) @@ -867,21 +857,21 @@ void D_Display () case GS_INTERMISSION: screen->SetBlendingRect(0,0,0,0); - hw2d = screen->Begin2D(false); + screen->Begin2D(false); WI_Drawer (); CT_Drawer (); break; case GS_FINALE: screen->SetBlendingRect(0,0,0,0); - hw2d = screen->Begin2D(false); + screen->Begin2D(false); F_Drawer (); CT_Drawer (); break; case GS_DEMOSCREEN: screen->SetBlendingRect(0,0,0,0); - hw2d = screen->Begin2D(false); + screen->Begin2D(false); D_PageDrawer (); CT_Drawer (); break; @@ -935,7 +925,7 @@ void D_Display () NetUpdate (); // send out any new accumulation // normal update // draw ZScript UI stuff - C_DrawConsole (hw2d); // draw console + C_DrawConsole (); // draw console M_Drawer (); // menu is drawn even on top of everything FStat::PrintStat (); screen->Update (); // page flip or blit buffer @@ -963,7 +953,7 @@ void D_Display () } while (diff < 1); wipestart = nowtime; done = screen->WipeDo (1); - C_DrawConsole (hw2d); // console and + C_DrawConsole (); // console and M_Drawer (); // menu are drawn even on top of wipes screen->Update (); // page flip or blit buffer NetUpdate (); // [RH] not sure this is needed anymore diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 287e2bcfc..8b3f40114 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -168,8 +168,6 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, NeedGammaUpdate = false; NeedPalUpdate = false; - RenderBuffer = new DSimpleCanvas(Width, Height, bgra); - memcpy(SourcePalette, GPalette.BaseColors, sizeof(PalEntry) * 256); // To do: this needs to cooperate with the same static in OpenGLFrameBuffer::InitializeState @@ -219,12 +217,19 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height, TrueHeight = height; Valid = CreateResources(); + + RenderBuffer = new DSimpleCanvas(Width, Height, bgra); + if (UseMappedMemBuffer) MappedBuffer = new DCanvas(Width, Height, bgra); + else MappedBuffer = nullptr; + if (Valid) SetInitialState(); } OpenGLSWFrameBuffer::~OpenGLSWFrameBuffer() { + if (RenderBuffer) delete RenderBuffer; + if (MappedBuffer) delete MappedBuffer; ReleaseResources(); delete[] QuadExtra; } @@ -771,7 +776,7 @@ void OpenGLSWFrameBuffer::Present() void OpenGLSWFrameBuffer::SetInitialState() { - //if (gl.es) re-enable later! First the basics must work. + if (gl.es) UseMappedMemBuffer = false; AlphaBlendEnabled = false; @@ -1109,16 +1114,8 @@ int OpenGLSWFrameBuffer::GetPageCount() // //========================================================================== -#if 0 -bool OpenGLSWFrameBuffer::Lock(bool buffered) +bool OpenGLSWFrameBuffer::LockCanvas() { - if (m_Lock++ > 0) - { - return false; - } - assert(!In2D); - -#if 0 // temporarily disabled. Must be fixed later if (UseMappedMemBuffer) { if (!MappedMemBuffer) @@ -1126,19 +1123,12 @@ bool OpenGLSWFrameBuffer::Lock(bool buffered) BindFBBuffer(); MappedMemBuffer = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE); - Pitch = Width; if (MappedMemBuffer == nullptr) - return true; + return false; glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } - Buffer = (uint8_t*)MappedMemBuffer; - } - else -#endif - { -#if 0 - //Buffer = MemBuffer; -#endif + MappedBuffer->SetBuffer(Width, Height, Width, static_cast(MappedMemBuffer)); + return true; } return false; } @@ -1149,33 +1139,17 @@ bool OpenGLSWFrameBuffer::Lock(bool buffered) // //========================================================================== -void OpenGLSWFrameBuffer::Unlock() +void OpenGLSWFrameBuffer::UnlockCanvas() { - if (m_Lock == 0) + if (MappedMemBuffer) { - return; - } - - if (UpdatePending && m_Lock == 1) - { - Update(); - } - else if (--m_Lock == 0) - { -#if 0 - Buffer = nullptr; -#endif - - if (MappedMemBuffer) - { - BindFBBuffer(); - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - MappedMemBuffer = nullptr; - } + BindFBBuffer(); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + MappedMemBuffer = nullptr; + MappedBuffer->SetBuffer(0, 0, 0, nullptr); } } -#endif //========================================================================== // diff --git a/src/gl/system/gl_swframebuffer.h b/src/gl/system/gl_swframebuffer.h index 5123526df..0d79c03b5 100644 --- a/src/gl/system/gl_swframebuffer.h +++ b/src/gl/system/gl_swframebuffer.h @@ -25,6 +25,7 @@ class OpenGLSWFrameBuffer : public SDLGLFB #endif DSimpleCanvas *RenderBuffer; + DCanvas *MappedBuffer; public: @@ -32,6 +33,9 @@ public: OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra); ~OpenGLSWFrameBuffer(); + bool LockCanvas() override; + void UnlockCanvas() override; + virtual DCanvas *GetCanvas() { return RenderBuffer; } void Update() override; PalEntry *GetPalette() override; diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index fb4fa4915..0a32e7d90 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -59,18 +59,22 @@ void PolyRenderer::RenderView(player_t *player) { using namespace swrenderer; - RenderTarget = screen->GetCanvas(); + if (screen->LockCanvas()) + { + RenderTarget = screen->GetCanvas(); - int width = SCREENWIDTH; - int height = SCREENHEIGHT; - float trueratio; - ActiveRatio(width, height, &trueratio); - //viewport->SetViewport(&Thread, width, height, trueratio); + int width = SCREENWIDTH; + int height = SCREENHEIGHT; + float trueratio; + ActiveRatio(width, height, &trueratio); + //viewport->SetViewport(&Thread, width, height, trueratio); - RenderActorView(player->mo, false); + RenderActorView(player->mo, false); - Threads.MainThread()->FlushDrawQueue(); - DrawerThreads::WaitForWorkers(); + Threads.MainThread()->FlushDrawQueue(); + DrawerThreads::WaitForWorkers(); + screen->UnlockCanvas(); + } } void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines) diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index 6118d2b15..566758b9c 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -89,36 +89,42 @@ namespace swrenderer void RenderScene::RenderView(player_t *player) { - auto viewport = MainThread()->Viewport.get(); - viewport->RenderTarget = screen->GetCanvas(); - - int width = SCREENWIDTH; - int height = SCREENHEIGHT; - float trueratio; - ActiveRatio(width, height, &trueratio); - viewport->SetViewport(MainThread(), width, height, trueratio); - - if (r_clearbuffer != 0) + if (screen->LockCanvas()) { - if (!viewport->RenderTarget->IsBgra()) + auto viewport = MainThread()->Viewport.get(); + viewport->RenderTarget = screen->GetCanvas(); + + int width = SCREENWIDTH; + int height = SCREENHEIGHT; + float trueratio; + ActiveRatio(width, height, &trueratio); + viewport->SetViewport(MainThread(), width, height, trueratio); + + if (r_clearbuffer != 0) { - memset(viewport->RenderTarget->GetPixels(), clearcolor, viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight()); - } - else - { - uint32_t bgracolor = GPalette.BaseColors[clearcolor].d; - int size = viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight(); - uint32_t *dest = (uint32_t *)viewport->RenderTarget->GetPixels(); - for (int i = 0; i < size; i++) - dest[i] = bgracolor; + if (!viewport->RenderTarget->IsBgra()) + { + memset(viewport->RenderTarget->GetPixels(), clearcolor, viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight()); + } + else + { + uint32_t bgracolor = GPalette.BaseColors[clearcolor].d; + int size = viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight(); + uint32_t *dest = (uint32_t *)viewport->RenderTarget->GetPixels(); + for (int i = 0; i < size; i++) + dest[i] = bgracolor; + } } + + RenderActorView(player->mo); + + DrawerWaitCycles.Clock(); + DrawerThreads::WaitForWorkers(); + DrawerWaitCycles.Unclock(); + + screen->UnlockCanvas(); } - RenderActorView(player->mo); - - DrawerWaitCycles.Clock(); - DrawerThreads::WaitForWorkers(); - DrawerWaitCycles.Unclock(); } void RenderScene::RenderActorView(AActor *actor, bool dontmaplines) diff --git a/src/v_video.h b/src/v_video.h index b7b1e0604..cd2b8420e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -206,13 +206,28 @@ public: virtual ~DCanvas (); // Member variable access - //inline uint8_t *GetBuffer () const { return Buffer; } inline uint8_t *GetPixels () const { return PixelBuffer; } inline int GetWidth () const { return Width; } inline int GetHeight () const { return Height; } inline int GetPitch () const { return Pitch; } inline bool IsBgra() const { return Bgra; } + bool SetBuffer(int width, int height, int pitch, uint8_t *buffer) + { + if (PixelBuffer == nullptr) + { + Width = width; + Height = height; + Pitch = pitch; + PixelBuffer = buffer; + return true; + } + else + { + return false; + } + } + protected: uint8_t *PixelBuffer; @@ -220,11 +235,6 @@ protected: int Height; int Pitch; bool Bgra; - - - DCanvas() {} - -private: }; // A canvas in system memory. @@ -236,10 +246,6 @@ public: DSimpleCanvas (int width, int height, bool bgra); ~DSimpleCanvas (); void Resize(int width, int height); - -private: - - DSimpleCanvas() {} }; // This class represents a native texture, as opposed to an FTexture. @@ -341,6 +347,10 @@ public: virtual bool LegacyHardware() const { return false; } // only for reporting SM1.4 support to the stat collector + // For FrameBuffers with a software canvas that requires special preparation before being used. + virtual bool LockCanvas() { return true; } + virtual void UnlockCanvas() {} + // Begin 2D drawing operations. This is like Update, but it doesn't end // the scene, and it doesn't present the image yet. If you are going to // be covering the entire screen with 2D elements, then pass false to