Mesen2/Core/Shared/Video/SoftwareRenderer.cpp

97 lines
2.5 KiB
C++

#include "pch.h"
#include "Shared/Video/SoftwareRenderer.h"
#include "Shared/Video/VideoRenderer.h"
#include "Shared/RenderedFrame.h"
#include "Shared/Emulator.h"
#include "Shared/NotificationManager.h"
SoftwareRenderer::SoftwareRenderer(Emulator* emu)
{
_emu = emu;
SetScreenSize(256, 240);
_emu->GetVideoRenderer()->RegisterRenderingDevice(this);
}
SoftwareRenderer::~SoftwareRenderer()
{
delete[] _textureBuffer[0];
delete[] _textureBuffer[1];
}
void SoftwareRenderer::SetScreenSize(uint32_t width, uint32_t height)
{
_frameWidth = width;
_frameHeight = height;
delete[] _textureBuffer[0];
delete[] _textureBuffer[1];
_textureBuffer[0] = new uint32_t[width * height];
_textureBuffer[1] = new uint32_t[width * height];
memset(_textureBuffer[0], 0, width * height * sizeof(uint32_t));
memset(_textureBuffer[1], 0, width * height * sizeof(uint32_t));
}
void SoftwareRenderer::UpdateFrame(RenderedFrame& frame)
{
if(_frameWidth != frame.Width || _frameHeight != frame.Height) {
auto lock = _frameLock.AcquireSafe();
if(_frameWidth != frame.Width || _frameHeight != frame.Height) {
SetScreenSize(frame.Width, frame.Height);
}
}
auto lock = _textureLock.AcquireSafe();
memcpy(_textureBuffer[0], frame.FrameBuffer, frame.Width * frame.Height * sizeof(uint32_t));
_needSwap = true;
}
void SoftwareRenderer::ClearFrame()
{
//Clear current output and display black frame
auto lock = _textureLock.AcquireSafe();
memset(_textureBuffer[0], 0, _frameWidth * _frameHeight * sizeof(uint32_t));
_needSwap = true;
}
struct SoftwareRendererSurface
{
uint32_t* Buffer = nullptr;
uint32_t Width = 0;
uint32_t Height = 0;
bool IsDirty = true;
};
struct SoftwareRendererFrame
{
SoftwareRendererSurface Frame;
SoftwareRendererSurface EmuHud;
SoftwareRendererSurface ScriptHud;
};
void SoftwareRenderer::Render(RenderSurfaceInfo& emuHud, RenderSurfaceInfo& scriptHud)
{
auto lock = _frameLock.AcquireSafe();
if(_needSwap) {
_needSwap = false;
auto textureLock = _textureLock.AcquireSafe();
std::swap(_textureBuffer[0], _textureBuffer[1]);
}
SoftwareRendererFrame frame = {
{ _textureBuffer[1], _frameWidth, _frameHeight, true },
{ emuHud.Buffer, emuHud.Width, emuHud.Height, emuHud.IsDirty },
{ scriptHud.Buffer, scriptHud.Width, scriptHud.Height, scriptHud.IsDirty }
};
_emu->GetNotificationManager()->SendNotification(ConsoleNotificationType::RefreshSoftwareRenderer, &frame);
}
void SoftwareRenderer::Reset()
{
}
void SoftwareRenderer::SetExclusiveFullscreenMode(bool fullscreen, void* windowHandle)
{
//not supported
}