- 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;
}
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)

View file

@ -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);

View file

@ -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

View file

@ -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<uint8_t*>(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
//==========================================================================
//

View file

@ -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;

View file

@ -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)

View file

@ -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)

View file

@ -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