- 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.
This commit is contained in:
Christoph Oelckers 2018-03-27 20:02:44 +02:00
parent 0c3635e22c
commit 2ed744963c
8 changed files with 100 additions and 127 deletions

View file

@ -1069,7 +1069,7 @@ void C_SetTicker (unsigned int at, bool forceUpdate)
TickerAt = at > TickerMax ? TickerMax : at; TickerAt = at > TickerMax ? TickerMax : at;
} }
void C_DrawConsole (bool hw2d) void C_DrawConsole ()
{ {
static int oldbottom = 0; static int oldbottom = 0;
int lines, left, offset; int lines, left, offset;
@ -1114,7 +1114,7 @@ void C_DrawConsole (bool hw2d)
DTA_DestWidth, screen->GetWidth(), DTA_DestWidth, screen->GetWidth(),
DTA_DestHeight, screen->GetHeight(), DTA_DestHeight, screen->GetHeight(),
DTA_ColorOverlay, conshade, 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, DTA_Masked, false,
TAG_DONE); TAG_DONE);
if (conline && visheight < screen->GetHeight()) 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) if (menuactive != MENU_Off)

View file

@ -67,7 +67,7 @@ void AddToConsole (int printlevel, const char *string);
int PrintString (int printlevel, const char *string); int PrintString (int printlevel, const char *string);
int VPrintf (int printlevel, const char *format, va_list parms) GCCFORMAT(2); 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_ToggleConsole (void);
void C_FullConsole (void); void C_FullConsole (void);
void C_HideConsole (void); void C_HideConsole (void);

View file

@ -669,7 +669,6 @@ CVAR (Flag, compat_pushwindow, compatflags2, COMPATF2_PUSHWINDOW);
void D_Display () void D_Display ()
{ {
bool wipe; bool wipe;
bool hw2d;
if (nodrawers || screen == NULL) if (nodrawers || screen == NULL)
return; // for comparative timing / profiling return; // for comparative timing / profiling
@ -774,9 +773,6 @@ void D_Display ()
wipe = false; wipe = false;
} }
hw2d = false;
{ {
screen->FrameTime = I_msTimeFS(); screen->FrameTime = I_msTimeFS();
TexMan.UpdateAnimations(screen->FrameTime); TexMan.UpdateAnimations(screen->FrameTime);
@ -785,8 +781,8 @@ void D_Display ()
{ {
case GS_FULLCONSOLE: case GS_FULLCONSOLE:
screen->SetBlendingRect(0,0,0,0); screen->SetBlendingRect(0,0,0,0);
hw2d = screen->Begin2D(false); screen->Begin2D(false);
C_DrawConsole (false); C_DrawConsole ();
M_Drawer (); M_Drawer ();
screen->Update (); screen->Update ();
return; return;
@ -795,10 +791,7 @@ void D_Display ()
case GS_TITLELEVEL: case GS_TITLELEVEL:
if (!gametic) if (!gametic)
{ {
if (!screen->HasBegun2D()) screen->Begin2D(false);
{
screen->Begin2D(false);
}
break; break;
} }
@ -815,11 +808,8 @@ void D_Display ()
// //
Renderer->RenderView(&players[consoleplayer]); Renderer->RenderView(&players[consoleplayer]);
if ((hw2d = screen->Begin2D(viewactive))) screen->Begin2D(viewactive);
{ V_SetBorderNeedRefresh();
// Redraw everything every frame when using 2D accel
V_SetBorderNeedRefresh();
}
Renderer->DrawRemainingPlayerSprites(); Renderer->DrawRemainingPlayerSprites();
screen->DrawBlendingRect(); screen->DrawBlendingRect();
if (automapactive) if (automapactive)
@ -867,21 +857,21 @@ void D_Display ()
case GS_INTERMISSION: case GS_INTERMISSION:
screen->SetBlendingRect(0,0,0,0); screen->SetBlendingRect(0,0,0,0);
hw2d = screen->Begin2D(false); screen->Begin2D(false);
WI_Drawer (); WI_Drawer ();
CT_Drawer (); CT_Drawer ();
break; break;
case GS_FINALE: case GS_FINALE:
screen->SetBlendingRect(0,0,0,0); screen->SetBlendingRect(0,0,0,0);
hw2d = screen->Begin2D(false); screen->Begin2D(false);
F_Drawer (); F_Drawer ();
CT_Drawer (); CT_Drawer ();
break; break;
case GS_DEMOSCREEN: case GS_DEMOSCREEN:
screen->SetBlendingRect(0,0,0,0); screen->SetBlendingRect(0,0,0,0);
hw2d = screen->Begin2D(false); screen->Begin2D(false);
D_PageDrawer (); D_PageDrawer ();
CT_Drawer (); CT_Drawer ();
break; break;
@ -935,7 +925,7 @@ void D_Display ()
NetUpdate (); // send out any new accumulation NetUpdate (); // send out any new accumulation
// normal update // normal update
// draw ZScript UI stuff // draw ZScript UI stuff
C_DrawConsole (hw2d); // draw console C_DrawConsole (); // draw console
M_Drawer (); // menu is drawn even on top of everything M_Drawer (); // menu is drawn even on top of everything
FStat::PrintStat (); FStat::PrintStat ();
screen->Update (); // page flip or blit buffer screen->Update (); // page flip or blit buffer
@ -963,7 +953,7 @@ void D_Display ()
} while (diff < 1); } while (diff < 1);
wipestart = nowtime; wipestart = nowtime;
done = screen->WipeDo (1); done = screen->WipeDo (1);
C_DrawConsole (hw2d); // console and C_DrawConsole (); // console and
M_Drawer (); // menu are drawn even on top of wipes M_Drawer (); // menu are drawn even on top of wipes
screen->Update (); // page flip or blit buffer screen->Update (); // page flip or blit buffer
NetUpdate (); // [RH] not sure this is needed anymore NetUpdate (); // [RH] not sure this is needed anymore

View file

@ -168,8 +168,6 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height,
NeedGammaUpdate = false; NeedGammaUpdate = false;
NeedPalUpdate = false; NeedPalUpdate = false;
RenderBuffer = new DSimpleCanvas(Width, Height, bgra);
memcpy(SourcePalette, GPalette.BaseColors, sizeof(PalEntry) * 256); memcpy(SourcePalette, GPalette.BaseColors, sizeof(PalEntry) * 256);
// To do: this needs to cooperate with the same static in OpenGLFrameBuffer::InitializeState // 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; TrueHeight = height;
Valid = CreateResources(); Valid = CreateResources();
RenderBuffer = new DSimpleCanvas(Width, Height, bgra);
if (UseMappedMemBuffer) MappedBuffer = new DCanvas(Width, Height, bgra);
else MappedBuffer = nullptr;
if (Valid) if (Valid)
SetInitialState(); SetInitialState();
} }
OpenGLSWFrameBuffer::~OpenGLSWFrameBuffer() OpenGLSWFrameBuffer::~OpenGLSWFrameBuffer()
{ {
if (RenderBuffer) delete RenderBuffer;
if (MappedBuffer) delete MappedBuffer;
ReleaseResources(); ReleaseResources();
delete[] QuadExtra; delete[] QuadExtra;
} }
@ -771,7 +776,7 @@ void OpenGLSWFrameBuffer::Present()
void OpenGLSWFrameBuffer::SetInitialState() void OpenGLSWFrameBuffer::SetInitialState()
{ {
//if (gl.es) re-enable later! First the basics must work. if (gl.es)
UseMappedMemBuffer = false; UseMappedMemBuffer = false;
AlphaBlendEnabled = false; AlphaBlendEnabled = false;
@ -1109,16 +1114,8 @@ int OpenGLSWFrameBuffer::GetPageCount()
// //
//========================================================================== //==========================================================================
#if 0 bool OpenGLSWFrameBuffer::LockCanvas()
bool OpenGLSWFrameBuffer::Lock(bool buffered)
{ {
if (m_Lock++ > 0)
{
return false;
}
assert(!In2D);
#if 0 // temporarily disabled. Must be fixed later
if (UseMappedMemBuffer) if (UseMappedMemBuffer)
{ {
if (!MappedMemBuffer) if (!MappedMemBuffer)
@ -1126,19 +1123,12 @@ bool OpenGLSWFrameBuffer::Lock(bool buffered)
BindFBBuffer(); BindFBBuffer();
MappedMemBuffer = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE); MappedMemBuffer = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
Pitch = Width;
if (MappedMemBuffer == nullptr) if (MappedMemBuffer == nullptr)
return true; return false;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} }
Buffer = (uint8_t*)MappedMemBuffer; MappedBuffer->SetBuffer(Width, Height, Width, static_cast<uint8_t*>(MappedMemBuffer));
} return true;
else
#endif
{
#if 0
//Buffer = MemBuffer;
#endif
} }
return false; return false;
} }
@ -1149,33 +1139,17 @@ bool OpenGLSWFrameBuffer::Lock(bool buffered)
// //
//========================================================================== //==========================================================================
void OpenGLSWFrameBuffer::Unlock() void OpenGLSWFrameBuffer::UnlockCanvas()
{ {
if (m_Lock == 0) if (MappedMemBuffer)
{ {
return; BindFBBuffer();
} glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
if (UpdatePending && m_Lock == 1) MappedMemBuffer = nullptr;
{ MappedBuffer->SetBuffer(0, 0, 0, nullptr);
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;
}
} }
} }
#endif
//========================================================================== //==========================================================================
// //

View file

@ -25,6 +25,7 @@ class OpenGLSWFrameBuffer : public SDLGLFB
#endif #endif
DSimpleCanvas *RenderBuffer; DSimpleCanvas *RenderBuffer;
DCanvas *MappedBuffer;
public: public:
@ -32,6 +33,9 @@ public:
OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra); OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra);
~OpenGLSWFrameBuffer(); ~OpenGLSWFrameBuffer();
bool LockCanvas() override;
void UnlockCanvas() override;
virtual DCanvas *GetCanvas() { return RenderBuffer; } virtual DCanvas *GetCanvas() { return RenderBuffer; }
void Update() override; void Update() override;
PalEntry *GetPalette() override; PalEntry *GetPalette() override;

View file

@ -59,18 +59,22 @@ void PolyRenderer::RenderView(player_t *player)
{ {
using namespace swrenderer; using namespace swrenderer;
RenderTarget = screen->GetCanvas(); if (screen->LockCanvas())
{
RenderTarget = screen->GetCanvas();
int width = SCREENWIDTH; int width = SCREENWIDTH;
int height = SCREENHEIGHT; int height = SCREENHEIGHT;
float trueratio; float trueratio;
ActiveRatio(width, height, &trueratio); ActiveRatio(width, height, &trueratio);
//viewport->SetViewport(&Thread, width, height, trueratio); //viewport->SetViewport(&Thread, width, height, trueratio);
RenderActorView(player->mo, false); RenderActorView(player->mo, false);
Threads.MainThread()->FlushDrawQueue(); Threads.MainThread()->FlushDrawQueue();
DrawerThreads::WaitForWorkers(); DrawerThreads::WaitForWorkers();
screen->UnlockCanvas();
}
} }
void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines) void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines)

View file

@ -89,36 +89,42 @@ namespace swrenderer
void RenderScene::RenderView(player_t *player) void RenderScene::RenderView(player_t *player)
{ {
auto viewport = MainThread()->Viewport.get(); if (screen->LockCanvas())
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 (!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()); if (!viewport->RenderTarget->IsBgra())
} {
else memset(viewport->RenderTarget->GetPixels(), clearcolor, viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight());
{ }
uint32_t bgracolor = GPalette.BaseColors[clearcolor].d; else
int size = viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight(); {
uint32_t *dest = (uint32_t *)viewport->RenderTarget->GetPixels(); uint32_t bgracolor = GPalette.BaseColors[clearcolor].d;
for (int i = 0; i < size; i++) int size = viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight();
dest[i] = bgracolor; 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) void RenderScene::RenderActorView(AActor *actor, bool dontmaplines)

View file

@ -206,13 +206,28 @@ public:
virtual ~DCanvas (); virtual ~DCanvas ();
// Member variable access // Member variable access
//inline uint8_t *GetBuffer () const { return Buffer; }
inline uint8_t *GetPixels () const { return PixelBuffer; } inline uint8_t *GetPixels () const { return PixelBuffer; }
inline int GetWidth () const { return Width; } inline int GetWidth () const { return Width; }
inline int GetHeight () const { return Height; } inline int GetHeight () const { return Height; }
inline int GetPitch () const { return Pitch; } inline int GetPitch () const { return Pitch; }
inline bool IsBgra() const { return Bgra; } 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: protected:
uint8_t *PixelBuffer; uint8_t *PixelBuffer;
@ -220,11 +235,6 @@ protected:
int Height; int Height;
int Pitch; int Pitch;
bool Bgra; bool Bgra;
DCanvas() {}
private:
}; };
// A canvas in system memory. // A canvas in system memory.
@ -236,10 +246,6 @@ public:
DSimpleCanvas (int width, int height, bool bgra); DSimpleCanvas (int width, int height, bool bgra);
~DSimpleCanvas (); ~DSimpleCanvas ();
void Resize(int width, int height); void Resize(int width, int height);
private:
DSimpleCanvas() {}
}; };
// This class represents a native texture, as opposed to an FTexture. // 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 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 // 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 // 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 // be covering the entire screen with 2D elements, then pass false to