OpenGL Renderer: Properly clear the framebuffer during a power-off condition, just like how SoftRasterizer does it. (Related to commit 66b5da1
and commit 759a039
. Fixes #234.)
- Also do a minor performance optimization by only doing the framebuffer clear once for each power-off condition, rather than repeatedly and unnecessarily clearing the framebuffer for each and every V-blank.
This commit is contained in:
parent
df22c6e14d
commit
3d573e150f
|
@ -3823,12 +3823,6 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels()
|
|||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if (this->_mappedFramebuffer != NULL)
|
||||
{
|
||||
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
this->_mappedFramebuffer = NULL;
|
||||
}
|
||||
|
||||
if (this->willFlipAndConvertFramebufferOnGPU)
|
||||
{
|
||||
// Both flips and converts the framebuffer on the GPU. No additional postprocessing
|
||||
|
@ -3926,6 +3920,12 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels()
|
|||
{
|
||||
// Read back the pixels in BGRA format, since legacy OpenGL devices may experience a performance
|
||||
// penalty if the readback is in any other format.
|
||||
if (this->_mappedFramebuffer != NULL)
|
||||
{
|
||||
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
this->_mappedFramebuffer = NULL;
|
||||
}
|
||||
|
||||
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
|
||||
|
@ -4913,6 +4913,51 @@ Render3DError OpenGLRenderer_1_2::Reset()
|
|||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLRenderer_1_2::RenderPowerOff()
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if (!this->_isPoweredOn)
|
||||
{
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
this->_isPoweredOn = false;
|
||||
memset(GPU->GetEngineMain()->Get3DFramebufferMain(), 0, this->_framebufferColorSizeBytes);
|
||||
memset(GPU->GetEngineMain()->Get3DFramebuffer16(), 0, this->_framebufferPixCount * sizeof(u16));
|
||||
|
||||
if(!BEGINGL())
|
||||
{
|
||||
return OGLERROR_BEGINGL_FAILED;
|
||||
}
|
||||
|
||||
if (this->isFBOSupported)
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||
}
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (this->isPBOSupported)
|
||||
{
|
||||
if (this->_mappedFramebuffer != NULL)
|
||||
{
|
||||
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
this->_mappedFramebuffer = NULL;
|
||||
}
|
||||
|
||||
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
|
||||
ENDGL();
|
||||
|
||||
this->_pixelReadNeedsFinish = true;
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLRenderer_1_2::RenderFinish()
|
||||
{
|
||||
if (!this->_renderNeedsFinish)
|
||||
|
@ -4949,6 +4994,11 @@ Render3DError OpenGLRenderer_1_2::RenderFinish()
|
|||
|
||||
Render3DError OpenGLRenderer_1_2::RenderFlush(bool willFlushBuffer32, bool willFlushBuffer16)
|
||||
{
|
||||
if (!this->_isPoweredOn)
|
||||
{
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
FragmentColor *framebufferMain = (willFlushBuffer32) ? GPU->GetEngineMain()->Get3DFramebufferMain() : NULL;
|
||||
u16 *framebuffer16 = (willFlushBuffer16) ? GPU->GetEngineMain()->Get3DFramebuffer16() : NULL;
|
||||
|
||||
|
@ -5257,6 +5307,11 @@ Render3DError OpenGLRenderer_2_1::RenderFinish()
|
|||
|
||||
Render3DError OpenGLRenderer_2_1::RenderFlush(bool willFlushBuffer32, bool willFlushBuffer16)
|
||||
{
|
||||
if (!this->_isPoweredOn)
|
||||
{
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
FragmentColor *framebufferMain = (willFlushBuffer32) ? GPU->GetEngineMain()->Get3DFramebufferMain() : NULL;
|
||||
u16 *framebuffer16 = (willFlushBuffer16) ? GPU->GetEngineMain()->Get3DFramebuffer16() : NULL;
|
||||
|
||||
|
|
|
@ -816,6 +816,7 @@ public:
|
|||
virtual Render3DError InitExtensions();
|
||||
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
|
||||
virtual Render3DError Reset();
|
||||
virtual Render3DError RenderPowerOff();
|
||||
virtual Render3DError RenderFinish();
|
||||
virtual Render3DError RenderFlush(bool willFlushBuffer32, bool willFlushBuffer16);
|
||||
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
|
||||
|
|
|
@ -1470,12 +1470,6 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels()
|
|||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if (this->_mappedFramebuffer != NULL)
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
this->_mappedFramebuffer = NULL;
|
||||
}
|
||||
|
||||
if (this->_outputFormat == NDSColorFormat_BGR666_Rev)
|
||||
{
|
||||
// Both flips and converts the framebuffer on the GPU. No additional postprocessing
|
||||
|
@ -1510,6 +1504,12 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels()
|
|||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
if (this->_mappedFramebuffer != NULL)
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
this->_mappedFramebuffer = NULL;
|
||||
}
|
||||
|
||||
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
else
|
||||
|
@ -1534,6 +1534,12 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels()
|
|||
|
||||
// Read back the pixels in RGBA format, since an OpenGL 3.2 device should be able to read back this
|
||||
// format without a performance penalty.
|
||||
if (this->_mappedFramebuffer != NULL)
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
this->_mappedFramebuffer = NULL;
|
||||
}
|
||||
|
||||
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
|
||||
|
@ -2075,3 +2081,41 @@ Render3DError OpenGLRenderer_3_2::SetFramebufferSize(size_t w, size_t h)
|
|||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLRenderer_3_2::RenderPowerOff()
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
static const GLfloat oglColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
if (!this->_isPoweredOn)
|
||||
{
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
this->_isPoweredOn = false;
|
||||
memset(GPU->GetEngineMain()->Get3DFramebufferMain(), 0, this->_framebufferColorSizeBytes);
|
||||
memset(GPU->GetEngineMain()->Get3DFramebuffer16(), 0, this->_framebufferPixCount * sizeof(u16));
|
||||
|
||||
if(!BEGINGL())
|
||||
{
|
||||
return OGLERROR_BEGINGL_FAILED;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glClearBufferfv(GL_COLOR, 0, oglColor);
|
||||
|
||||
if (this->_mappedFramebuffer != NULL)
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
this->_mappedFramebuffer = NULL;
|
||||
}
|
||||
|
||||
glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
|
||||
ENDGL();
|
||||
|
||||
this->_pixelReadNeedsFinish = true;
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 shash
|
||||
Copyright (C) 2008-2016 DeSmuME team
|
||||
Copyright (C) 2008-2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -106,6 +106,8 @@ protected:
|
|||
|
||||
public:
|
||||
~OpenGLRenderer_3_2();
|
||||
|
||||
virtual Render3DError RenderPowerOff();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2506,10 +2506,7 @@ void gfx3d_VBlankEndSignal(bool skipFrame)
|
|||
}
|
||||
else
|
||||
{
|
||||
memset(GPU->GetEngineMain()->Get3DFramebufferMain(), 0, GPU->GetCustomFramebufferWidth() * GPU->GetCustomFramebufferHeight() * sizeof(FragmentColor));
|
||||
memset(GPU->GetEngineMain()->Get3DFramebuffer16(), 0, GPU->GetCustomFramebufferWidth() * GPU->GetCustomFramebufferHeight() * sizeof(u16));
|
||||
CurrentRenderer->SetRenderNeedsFinish(false);
|
||||
GPU->GetEventHandler()->DidRender3DEnd();
|
||||
CurrentRenderer->RenderPowerOff();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2529,6 +2529,7 @@ Render3DError SoftRasterizerRenderer::Reset()
|
|||
Render3DError SoftRasterizerRenderer::Render(const GFX3D &engine)
|
||||
{
|
||||
Render3DError error = RENDER3DERROR_NOERR;
|
||||
this->_isPoweredOn = true;
|
||||
|
||||
error = this->BeginRender(engine);
|
||||
if (error != RENDER3DERROR_NOERR)
|
||||
|
@ -2609,6 +2610,11 @@ Render3DError SoftRasterizerRenderer::RenderFinish()
|
|||
|
||||
Render3DError SoftRasterizerRenderer::RenderFlush(bool willFlushBuffer32, bool willFlushBuffer16)
|
||||
{
|
||||
if (!this->_isPoweredOn)
|
||||
{
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
FragmentColor *framebufferMain = (willFlushBuffer32 && (this->_outputFormat == NDSColorFormat_BGR888_Rev)) ? GPU->GetEngineMain()->Get3DFramebufferMain() : NULL;
|
||||
u16 *framebuffer16 = (willFlushBuffer16) ? GPU->GetEngineMain()->Get3DFramebuffer16() : NULL;
|
||||
this->FlushFramebuffer(this->_framebufferColor, framebufferMain, framebuffer16);
|
||||
|
|
|
@ -220,6 +220,7 @@ Render3D::Render3D()
|
|||
_renderNeedsFinish = false;
|
||||
_renderNeedsFlushMain = false;
|
||||
_renderNeedsFlush16 = false;
|
||||
_isPoweredOn = false;
|
||||
|
||||
_textureUpscaleBuffer = NULL;
|
||||
|
||||
|
@ -673,15 +674,31 @@ Render3DError Render3D::Reset()
|
|||
this->_renderNeedsFinish = false;
|
||||
this->_renderNeedsFlushMain = false;
|
||||
this->_renderNeedsFlush16 = false;
|
||||
this->_isPoweredOn = false;
|
||||
|
||||
texCache.Reset();
|
||||
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError Render3D::RenderPowerOff()
|
||||
{
|
||||
if (!this->_isPoweredOn)
|
||||
{
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
this->_isPoweredOn = false;
|
||||
memset(GPU->GetEngineMain()->Get3DFramebufferMain(), 0, this->_framebufferColorSizeBytes);
|
||||
memset(GPU->GetEngineMain()->Get3DFramebuffer16(), 0, this->_framebufferPixCount * sizeof(u16));
|
||||
|
||||
return RENDER3DERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError Render3D::Render(const GFX3D &engine)
|
||||
{
|
||||
Render3DError error = RENDER3DERROR_NOERR;
|
||||
this->_isPoweredOn = true;
|
||||
|
||||
error = this->BeginRender(engine);
|
||||
if (error != RENDER3DERROR_NOERR)
|
||||
|
|
|
@ -162,6 +162,7 @@ protected:
|
|||
bool _renderNeedsFinish;
|
||||
bool _renderNeedsFlushMain;
|
||||
bool _renderNeedsFlush16;
|
||||
bool _isPoweredOn;
|
||||
|
||||
bool _enableEdgeMark;
|
||||
bool _enableFog;
|
||||
|
@ -223,6 +224,8 @@ public:
|
|||
|
||||
virtual Render3DError Reset(); // Called when the emulator resets.
|
||||
|
||||
virtual Render3DError RenderPowerOff(); // Called when the renderer needs to handle a power-off condition by clearing its framebuffers.
|
||||
|
||||
virtual Render3DError Render(const GFX3D &engine); // Called when the renderer should do its job and render the current display lists.
|
||||
|
||||
virtual Render3DError RenderFinish(); // Called whenever 3D rendering needs to finish. This function should block the calling thread
|
||||
|
|
Loading…
Reference in New Issue