diff --git a/Linux/SdlRenderer.cpp b/Linux/SdlRenderer.cpp index 4fe636f5..c57759e2 100755 --- a/Linux/SdlRenderer.cpp +++ b/Linux/SdlRenderer.cpp @@ -5,13 +5,18 @@ #include "../Core/VideoDecoder.h" #include "../Core/EmulationSettings.h" -SimpleLock SdlRenderer::_reinitLock; SimpleLock SdlRenderer::_frameLock; SdlRenderer::SdlRenderer(shared_ptr console, void* windowHandle, bool registerAsMessageManager) : BaseRenderer(console, registerAsMessageManager), _windowHandle(windowHandle) { _frameBuffer = nullptr; - SetScreenSize(256,240); + _requiredWidth = 256; + _requiredHeight = 240; + + shared_ptr videoRenderer = _console->GetVideoRenderer(); + if(videoRenderer) { + _console->GetVideoRenderer()->RegisterRenderingDevice(this); + } } SdlRenderer::~SdlRenderer() @@ -20,7 +25,10 @@ SdlRenderer::~SdlRenderer() if(videoRenderer) { videoRenderer->UnregisterRenderingDevice(this); } + + auto lock = _frameLock.AcquireSafe(); Cleanup(); + delete[] _frameBuffer; } void SdlRenderer::SetFullscreenMode(bool fullscreen, void* windowHandle, uint32_t monitorWidth, uint32_t monitorHeight) @@ -69,7 +77,8 @@ bool SdlRenderer::Init() _sdlTexture = SDL_CreateTexture(_sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, _nesFrameWidth, _nesFrameHeight); if(!_sdlTexture) { - log("[SDL] Failed to create texture."); + string msg = "[SDL] Failed to create texture: " + std::to_string(_nesFrameWidth) + "x" + std::to_string(_nesFrameHeight); + log(msg.c_str()); return false; } @@ -78,9 +87,6 @@ bool SdlRenderer::Init() SDL_SetWindowSize(_sdlWindow, _screenWidth, _screenHeight); - _frameBuffer = new uint32_t[_nesFrameHeight*_nesFrameWidth]; - memset(_frameBuffer, 0, _nesFrameHeight*_nesFrameWidth*_bytesPerPixel); - return true; } @@ -94,10 +100,6 @@ void SdlRenderer::Cleanup() SDL_DestroyRenderer(_sdlRenderer); _sdlRenderer = nullptr; } - if(_frameBuffer) { - delete[] _frameBuffer; - _frameBuffer = nullptr; - } } void SdlRenderer::Reset() @@ -116,8 +118,6 @@ void SdlRenderer::SetScreenSize(uint32_t width, uint32_t height) _console->GetVideoDecoder()->GetScreenSize(screenSize, false); if(_screenHeight != (uint32_t)screenSize.Height || _screenWidth != (uint32_t)screenSize.Width || _nesFrameHeight != height || _nesFrameWidth != width || _resizeFilter != _console->GetSettings()->GetVideoResizeFilter() || _vsyncEnabled != _console->GetSettings()->CheckFlag(EmulationFlags::VerticalSync)) { - _reinitLock.Acquire(); - _vsyncEnabled = _console->GetSettings()->CheckFlag(EmulationFlags::VerticalSync); _nesFrameHeight = height; @@ -133,14 +133,21 @@ void SdlRenderer::SetScreenSize(uint32_t width, uint32_t height) _screenBufferSize = _screenHeight*_screenWidth; Reset(); - _reinitLock.Release(); } } void SdlRenderer::UpdateFrame(void *frameBuffer, uint32_t width, uint32_t height) { - SetScreenSize(width, height); _frameLock.Acquire(); + if(_frameBuffer == nullptr || _requiredWidth != width || _requiredHeight != height) { + _requiredWidth = width; + _requiredHeight = height; + + delete[] _frameBuffer; + _frameBuffer = new uint32_t[width*height]; + memset(_frameBuffer, 0, width*height*4); + } + memcpy(_frameBuffer, frameBuffer, width*height*_bytesPerPixel); _frameChanged = true; _frameLock.Release(); @@ -148,10 +155,12 @@ void SdlRenderer::UpdateFrame(void *frameBuffer, uint32_t width, uint32_t height void SdlRenderer::Render() { + SetScreenSize(_requiredWidth, _requiredHeight); + if(!_sdlRenderer || !_sdlTexture) { return; } - + bool paused = _console->IsPaused() && _console->IsRunning(); bool disableOverlay = _console->GetSettings()->CheckFlag(EmulationFlags::HidePauseOverlay); shared_ptr debugger = _console->GetDebugger(false); @@ -161,8 +170,6 @@ void SdlRenderer::Render() } if(_noUpdateCount > 10 || _frameChanged || paused || IsMessageShown()) { - auto lock = _reinitLock.AcquireSafe(); - SDL_RenderClear(_sdlRenderer); uint8_t *textureBuffer; @@ -170,11 +177,13 @@ void SdlRenderer::Render() SDL_LockTexture(_sdlTexture, nullptr, (void**)&textureBuffer, &rowPitch); { auto frameLock = _frameLock.AcquireSafe(); - uint32_t* ppuFrameBuffer = _frameBuffer; - for(uint32_t i = 0, iMax = _nesFrameHeight; i < iMax; i++) { - memcpy(textureBuffer, ppuFrameBuffer, _nesFrameWidth*_bytesPerPixel); - ppuFrameBuffer += _nesFrameWidth; - textureBuffer += rowPitch; + if(_frameBuffer && _nesFrameWidth == _requiredWidth && _nesFrameHeight == _requiredHeight) { + uint32_t* ppuFrameBuffer = _frameBuffer; + for(uint32_t i = 0, iMax = _nesFrameHeight; i < iMax; i++) { + memcpy(textureBuffer, ppuFrameBuffer, _nesFrameWidth*_bytesPerPixel); + ppuFrameBuffer += _nesFrameWidth; + textureBuffer += rowPitch; + } } } SDL_UnlockTexture(_sdlTexture); @@ -247,4 +256,4 @@ float SdlRenderer::MeasureString(std::wstring text) bool SdlRenderer::ContainsCharacter(wchar_t character) { return _spriteFont->ContainsCharacter(character); -} \ No newline at end of file +} diff --git a/Linux/SdlRenderer.h b/Linux/SdlRenderer.h index 55730ef5..3b1cce0b 100755 --- a/Linux/SdlRenderer.h +++ b/Linux/SdlRenderer.h @@ -26,7 +26,7 @@ class Console; class SdlRenderer : public IRenderingDevice, public BaseRenderer { private: - void* _windowHandle; + void* _windowHandle = nullptr; SDL_Window* _sdlWindow = nullptr; SDL_Renderer *_sdlRenderer = nullptr; SDL_Texture *_sdlTexture = nullptr; @@ -36,8 +36,7 @@ private: VideoResizeFilter _resizeFilter = VideoResizeFilter::NearestNeighbor; static SimpleLock _frameLock; - static SimpleLock _reinitLock; - uint32_t* _frameBuffer; + uint32_t* _frameBuffer = nullptr; const uint32_t _bytesPerPixel = 4; uint32_t _screenBufferSize = 0; @@ -45,6 +44,9 @@ private: bool _frameChanged = true; uint32_t _noUpdateCount = 0; + uint32_t _requiredHeight = 0; + uint32_t _requiredWidth = 0; + uint32_t _nesFrameHeight = 0; uint32_t _nesFrameWidth = 0; uint32_t _newFrameBufferSize = 0; @@ -71,4 +73,4 @@ public: void DrawString(std::wstring message, int x, int y, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255, uint8_t opacity = 255) override; void SetFullscreenMode(bool fullscreen, void* windowHandle, uint32_t monitorWidth, uint32_t monitorHeight) override; -}; \ No newline at end of file +};