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)
|
||||
|
|
|
@ -68,13 +68,13 @@ enum RendererID
|
|||
enum Render3DErrorCode
|
||||
{
|
||||
RENDER3DERROR_NOERR = 0
|
||||
};
|
||||
|
||||
enum PolyFacing
|
||||
{
|
||||
PolyFacing_Unwritten = 0,
|
||||
PolyFacing_Front = 1,
|
||||
PolyFacing_Back = 2
|
||||
};
|
||||
|
||||
enum PolyFacing
|
||||
{
|
||||
PolyFacing_Unwritten = 0,
|
||||
PolyFacing_Front = 1,
|
||||
PolyFacing_Back = 2
|
||||
};
|
||||
|
||||
typedef int Render3DError;
|
||||
|
@ -86,7 +86,7 @@ struct FragmentAttributes
|
|||
u8 translucentPolyID;
|
||||
u8 stencil;
|
||||
u8 isFogged;
|
||||
u8 isTranslucentPoly;
|
||||
u8 isTranslucentPoly;
|
||||
u8 polyFacing;
|
||||
};
|
||||
|
||||
|
@ -98,7 +98,7 @@ struct FragmentAttributesBuffer
|
|||
u8 *translucentPolyID;
|
||||
u8 *stencil;
|
||||
u8 *isFogged;
|
||||
u8 *isTranslucentPoly;
|
||||
u8 *isTranslucentPoly;
|
||||
u8 *polyFacing;
|
||||
|
||||
FragmentAttributesBuffer(size_t newCount);
|
||||
|
@ -144,15 +144,15 @@ public:
|
|||
size_t GetScalingFactor() const;
|
||||
void SetScalingFactor(size_t scalingFactor);
|
||||
};
|
||||
|
||||
|
||||
class Render3D
|
||||
{
|
||||
protected:
|
||||
Render3DDeviceInfo _deviceInfo;
|
||||
|
||||
size_t _framebufferWidth;
|
||||
size_t _framebufferHeight;
|
||||
size_t _framebufferPixCount;
|
||||
size_t _framebufferHeight;
|
||||
size_t _framebufferPixCount;
|
||||
size_t _framebufferSIMDPixCount;
|
||||
size_t _framebufferColorSizeBytes;
|
||||
FragmentColor *_framebufferColor;
|
||||
|
@ -162,6 +162,7 @@ protected:
|
|||
bool _renderNeedsFinish;
|
||||
bool _renderNeedsFlushMain;
|
||||
bool _renderNeedsFlush16;
|
||||
bool _isPoweredOn;
|
||||
|
||||
bool _enableEdgeMark;
|
||||
bool _enableFog;
|
||||
|
@ -183,10 +184,10 @@ protected:
|
|||
CACHE_ALIGN u16 clearImageColor16Buffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
CACHE_ALIGN u32 clearImageDepthBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
CACHE_ALIGN u8 clearImageFogBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
CACHE_ALIGN u8 clearImagePolyIDBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
|
||||
template<bool ISCOLORBLANK, bool ISDEPTHBLANK> void _ClearImageScrolledLoop(const u8 xScroll, const u8 yScroll, const u16 *__restrict inColor16, const u16 *__restrict inDepth16, const u8 inPolyID,
|
||||
u16 *__restrict outColor16, u32 *__restrict outDepth24, u8 *__restrict outFog, u8 *__restrict outPolyID);
|
||||
CACHE_ALIGN u8 clearImagePolyIDBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
|
||||
|
||||
template<bool ISCOLORBLANK, bool ISDEPTHBLANK> void _ClearImageScrolledLoop(const u8 xScroll, const u8 yScroll, const u16 *__restrict inColor16, const u16 *__restrict inDepth16, const u8 inPolyID,
|
||||
u16 *__restrict outColor16, u32 *__restrict outDepth24, u8 *__restrict outFog, u8 *__restrict outPolyID);
|
||||
|
||||
|
||||
virtual Render3DError BeginRender(const GFX3D &engine);
|
||||
|
@ -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
|
||||
|
@ -258,37 +261,37 @@ public:
|
|||
|
||||
void SetTextureProcessingProperties();
|
||||
Render3DTexture* GetTextureByPolygonRenderIndex(size_t polyRenderIndex) const;
|
||||
};
|
||||
|
||||
template <size_t SIMDBYTES>
|
||||
class Render3D_SIMD : public Render3D
|
||||
{
|
||||
public:
|
||||
Render3D_SIMD();
|
||||
|
||||
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
|
||||
};
|
||||
|
||||
#if defined(ENABLE_AVX2)
|
||||
|
||||
class Render3D_AVX2 : public Render3D_SIMD<32>
|
||||
{
|
||||
public:
|
||||
virtual Render3DError ClearFramebuffer(const GFX3D_State &renderState);
|
||||
};
|
||||
|
||||
#elif defined(ENABLE_SSE2)
|
||||
|
||||
template <size_t SIMDBYTES>
|
||||
class Render3D_SIMD : public Render3D
|
||||
{
|
||||
public:
|
||||
Render3D_SIMD();
|
||||
|
||||
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
|
||||
};
|
||||
|
||||
#if defined(ENABLE_AVX2)
|
||||
|
||||
class Render3D_AVX2 : public Render3D_SIMD<32>
|
||||
{
|
||||
public:
|
||||
virtual Render3DError ClearFramebuffer(const GFX3D_State &renderState);
|
||||
};
|
||||
|
||||
#elif defined(ENABLE_SSE2)
|
||||
|
||||
class Render3D_SSE2 : public Render3D_SIMD<16>
|
||||
{
|
||||
public:
|
||||
virtual Render3DError ClearFramebuffer(const GFX3D_State &renderState);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#elif defined(ENABLE_ALTIVEC)
|
||||
|
||||
class Render3D_Altivec : public Render3D_SIMD<16>
|
||||
{};
|
||||
|
||||
class Render3D_Altivec : public Render3D_SIMD<16>
|
||||
{};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue