diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index eefeb36f1..8a31c4fd3 100755 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -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; diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index 84d6085e8..e883cf451 100755 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -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); diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 029be9fa7..8e847c6a3 100644 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -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; +} diff --git a/desmume/src/OGLRender_3_2.h b/desmume/src/OGLRender_3_2.h index 516e2a23e..171102fc1 100644 --- a/desmume/src/OGLRender_3_2.h +++ b/desmume/src/OGLRender_3_2.h @@ -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 diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index fbd442637..452b605af 100755 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -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(); } } diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index cd45134e8..cad782499 100755 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -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); diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index 6b0815d75..b07fb9229 100755 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -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) diff --git a/desmume/src/render3D.h b/desmume/src/render3D.h index 5982ad172..f9464c95f 100644 --- a/desmume/src/render3D.h +++ b/desmume/src/render3D.h @@ -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 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 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 -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 +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