Linux: Fixed black screen when loading a game with nvidia drivers

This commit is contained in:
Sour 2019-12-28 20:54:25 +00:00
parent 5e900992d0
commit 9581fdf51b
2 changed files with 35 additions and 25 deletions

View file

@ -6,13 +6,18 @@
#include "../Core/EmuSettings.h" #include "../Core/EmuSettings.h"
#include "../Core/MessageManager.h" #include "../Core/MessageManager.h"
SimpleLock SdlRenderer::_reinitLock;
SimpleLock SdlRenderer::_frameLock; SimpleLock SdlRenderer::_frameLock;
SdlRenderer::SdlRenderer(shared_ptr<Console> console, void* windowHandle, bool registerAsMessageManager) : BaseRenderer(console, registerAsMessageManager), _windowHandle(windowHandle) SdlRenderer::SdlRenderer(shared_ptr<Console> console, void* windowHandle, bool registerAsMessageManager) : BaseRenderer(console, registerAsMessageManager), _windowHandle(windowHandle)
{ {
_frameBuffer = nullptr; _frameBuffer = nullptr;
SetScreenSize(512,480); _requiredWidth = 256;
_requiredHeight = 240;
shared_ptr<VideoRenderer> videoRenderer = _console->GetVideoRenderer();
if(videoRenderer) {
_console->GetVideoRenderer()->RegisterRenderingDevice(this);
}
} }
SdlRenderer::~SdlRenderer() SdlRenderer::~SdlRenderer()
@ -22,6 +27,8 @@ SdlRenderer::~SdlRenderer()
videoRenderer->UnregisterRenderingDevice(this); videoRenderer->UnregisterRenderingDevice(this);
} }
Cleanup(); Cleanup();
Cleanup();
delete[] _frameBuffer;
} }
void SdlRenderer::SetFullscreenMode(bool fullscreen, void* windowHandle, uint32_t monitorWidth, uint32_t monitorHeight) void SdlRenderer::SetFullscreenMode(bool fullscreen, void* windowHandle, uint32_t monitorWidth, uint32_t monitorHeight)
@ -70,7 +77,8 @@ bool SdlRenderer::Init()
_sdlTexture = SDL_CreateTexture(_sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, _nesFrameWidth, _nesFrameHeight); _sdlTexture = SDL_CreateTexture(_sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, _nesFrameWidth, _nesFrameHeight);
if(!_sdlTexture) { 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; return false;
} }
@ -79,9 +87,6 @@ bool SdlRenderer::Init()
SDL_SetWindowSize(_sdlWindow, _screenWidth, _screenHeight); SDL_SetWindowSize(_sdlWindow, _screenWidth, _screenHeight);
_frameBuffer = new uint32_t[_nesFrameHeight*_nesFrameWidth];
memset(_frameBuffer, 0, _nesFrameHeight*_nesFrameWidth*_bytesPerPixel);
return true; return true;
} }
@ -95,10 +100,6 @@ void SdlRenderer::Cleanup()
SDL_DestroyRenderer(_sdlRenderer); SDL_DestroyRenderer(_sdlRenderer);
_sdlRenderer = nullptr; _sdlRenderer = nullptr;
} }
if(_frameBuffer) {
delete[] _frameBuffer;
_frameBuffer = nullptr;
}
} }
void SdlRenderer::Reset() void SdlRenderer::Reset()
@ -117,8 +118,6 @@ void SdlRenderer::SetScreenSize(uint32_t width, uint32_t height)
VideoConfig cfg = _console->GetSettings()->GetVideoConfig(); VideoConfig cfg = _console->GetSettings()->GetVideoConfig();
if(_screenHeight != (uint32_t)screenSize.Height || _screenWidth != (uint32_t)screenSize.Width || _nesFrameHeight != height || _nesFrameWidth != width || _useBilinearInterpolation != cfg.UseBilinearInterpolation || _vsyncEnabled != cfg.VerticalSync) { if(_screenHeight != (uint32_t)screenSize.Height || _screenWidth != (uint32_t)screenSize.Width || _nesFrameHeight != height || _nesFrameWidth != width || _useBilinearInterpolation != cfg.UseBilinearInterpolation || _vsyncEnabled != cfg.VerticalSync) {
_reinitLock.Acquire();
_vsyncEnabled = cfg.VerticalSync; _vsyncEnabled = cfg.VerticalSync;
_useBilinearInterpolation = cfg.UseBilinearInterpolation; _useBilinearInterpolation = cfg.UseBilinearInterpolation;
@ -133,14 +132,21 @@ void SdlRenderer::SetScreenSize(uint32_t width, uint32_t height)
_screenBufferSize = _screenHeight*_screenWidth; _screenBufferSize = _screenHeight*_screenWidth;
Reset(); Reset();
_reinitLock.Release();
} }
} }
void SdlRenderer::UpdateFrame(void *frameBuffer, uint32_t width, uint32_t height) void SdlRenderer::UpdateFrame(void *frameBuffer, uint32_t width, uint32_t height)
{ {
SetScreenSize(width, height);
_frameLock.Acquire(); _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); memcpy(_frameBuffer, frameBuffer, width*height*_bytesPerPixel);
_frameChanged = true; _frameChanged = true;
_frameLock.Release(); _frameLock.Release();
@ -148,6 +154,8 @@ void SdlRenderer::UpdateFrame(void *frameBuffer, uint32_t width, uint32_t height
void SdlRenderer::Render() void SdlRenderer::Render()
{ {
SetScreenSize(_requiredWidth, _requiredHeight);
if(!_sdlRenderer || !_sdlTexture) { if(!_sdlRenderer || !_sdlTexture) {
return; return;
} }
@ -155,8 +163,6 @@ void SdlRenderer::Render()
bool paused = _console->IsPaused() && _console->IsRunning(); bool paused = _console->IsPaused() && _console->IsRunning();
if(_noUpdateCount > 10 || _frameChanged || paused || IsMessageShown()) { if(_noUpdateCount > 10 || _frameChanged || paused || IsMessageShown()) {
auto lock = _reinitLock.AcquireSafe();
SDL_RenderClear(_sdlRenderer); SDL_RenderClear(_sdlRenderer);
uint8_t *textureBuffer; uint8_t *textureBuffer;
@ -164,11 +170,13 @@ void SdlRenderer::Render()
SDL_LockTexture(_sdlTexture, nullptr, (void**)&textureBuffer, &rowPitch); SDL_LockTexture(_sdlTexture, nullptr, (void**)&textureBuffer, &rowPitch);
{ {
auto frameLock = _frameLock.AcquireSafe(); auto frameLock = _frameLock.AcquireSafe();
uint32_t* ppuFrameBuffer = _frameBuffer; if(_frameBuffer && _nesFrameWidth == _requiredWidth && _nesFrameHeight == _requiredHeight) {
for(uint32_t i = 0, iMax = _nesFrameHeight; i < iMax; i++) { uint32_t* ppuFrameBuffer = _frameBuffer;
memcpy(textureBuffer, ppuFrameBuffer, _nesFrameWidth*_bytesPerPixel); for(uint32_t i = 0, iMax = _nesFrameHeight; i < iMax; i++) {
ppuFrameBuffer += _nesFrameWidth; memcpy(textureBuffer, ppuFrameBuffer, _nesFrameWidth*_bytesPerPixel);
textureBuffer += rowPitch; ppuFrameBuffer += _nesFrameWidth;
textureBuffer += rowPitch;
}
} }
} }
SDL_UnlockTexture(_sdlTexture); SDL_UnlockTexture(_sdlTexture);
@ -217,4 +225,4 @@ float SdlRenderer::MeasureString(std::wstring text)
bool SdlRenderer::ContainsCharacter(wchar_t character) bool SdlRenderer::ContainsCharacter(wchar_t character)
{ {
return _spriteFont->ContainsCharacter(character); return _spriteFont->ContainsCharacter(character);
} }

View file

@ -35,8 +35,7 @@ private:
bool _useBilinearInterpolation = false; bool _useBilinearInterpolation = false;
static SimpleLock _frameLock; static SimpleLock _frameLock;
static SimpleLock _reinitLock; uint32_t* _frameBuffer = nullptr;
uint32_t* _frameBuffer;
const uint32_t _bytesPerPixel = 4; const uint32_t _bytesPerPixel = 4;
uint32_t _screenBufferSize = 0; uint32_t _screenBufferSize = 0;
@ -44,6 +43,9 @@ private:
bool _frameChanged = true; bool _frameChanged = true;
uint32_t _noUpdateCount = 0; uint32_t _noUpdateCount = 0;
uint32_t _requiredHeight = 0;
uint32_t _requiredWidth = 0;
uint32_t _nesFrameHeight = 0; uint32_t _nesFrameHeight = 0;
uint32_t _nesFrameWidth = 0; uint32_t _nesFrameWidth = 0;
uint32_t _newFrameBufferSize = 0; uint32_t _newFrameBufferSize = 0;
@ -70,4 +72,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 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; void SetFullscreenMode(bool fullscreen, void* windowHandle, uint32_t monitorWidth, uint32_t monitorHeight) override;
}; };