GPU/SDL: Correct aspect ratio when displaying

This commit is contained in:
Connor McLaughlin 2019-09-28 00:53:11 +10:00
parent 5184ad9d8b
commit 1400534127
5 changed files with 40 additions and 10 deletions

View file

@ -371,12 +371,38 @@ void SDLInterface::Render()
ImGui::NewFrame(); ImGui::NewFrame();
} }
static std::tuple<int, int, int, int> CalculateDrawRect(int window_width, int window_height, float display_ratio)
{
const float window_ratio = float(window_width) / float(window_height);
int left, top, width, height;
if (window_ratio >= display_ratio)
{
width = static_cast<int>(float(window_height) * display_ratio);
height = static_cast<int>(window_height);
left = (window_width - width) / 2;
top = 0;
}
else
{
width = static_cast<int>(window_width);
height = static_cast<int>(float(window_width) / display_ratio);
left = 0;
top = (window_height - height) / 2;
}
return std::tie(left, top, width, height);
}
void SDLInterface::RenderDisplay() void SDLInterface::RenderDisplay()
{ {
if (!m_display_texture) if (!m_display_texture)
return; return;
glViewport(0, 0, m_window_width, m_window_height - 20); // - 20 for main menu padding
const auto [vp_left, vp_top, vp_width, vp_height] =
CalculateDrawRect(m_window_width, std::max(m_window_height - 20, 1), m_display_aspect_ratio);
glViewport(vp_left, m_window_height - (20 + vp_top) - vp_height, vp_width, vp_height);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
@ -473,13 +499,15 @@ void SDLInterface::AddOSDMessage(const char* message, float duration /*= 2.0f*/)
m_osd_messages.push_back(std::move(msg)); m_osd_messages.push_back(std::move(msg));
} }
void SDLInterface::SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height) void SDLInterface::SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height,
float aspect_ratio)
{ {
m_display_texture = texture; m_display_texture = texture;
m_display_texture_offset_x = 0; m_display_texture_offset_x = offset_x;
m_display_texture_offset_y = 0; m_display_texture_offset_y = offset_y;
m_display_texture_width = width; m_display_texture_width = width;
m_display_texture_height = height; m_display_texture_height = height;
m_display_aspect_ratio = aspect_ratio;
m_display_texture_changed = true; m_display_texture_changed = true;
} }

View file

@ -23,7 +23,7 @@ public:
static TinyString GetSaveStateFilename(u32 index); static TinyString GetSaveStateFilename(u32 index);
void SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height) override; void SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height, float aspect_ratio) override;
void ReportMessage(const char* message) override; void ReportMessage(const char* message) override;
@ -70,6 +70,7 @@ private:
u32 m_display_texture_offset_y = 0; u32 m_display_texture_offset_y = 0;
u32 m_display_texture_width = 0; u32 m_display_texture_width = 0;
u32 m_display_texture_height = 0; u32 m_display_texture_height = 0;
float m_display_aspect_ratio = 1.0f;
bool m_display_texture_changed = false; bool m_display_texture_changed = false;
std::deque<OSDMessage> m_osd_messages; std::deque<OSDMessage> m_osd_messages;

View file

@ -37,6 +37,7 @@ public:
void Execute(TickCount ticks); void Execute(TickCount ticks);
protected: protected:
static constexpr float DISPLAY_ASPECT_RATIO = 4.0f / 3.0f;
static constexpr u32 VRAM_WIDTH = 1024; static constexpr u32 VRAM_WIDTH = 1024;
static constexpr u32 VRAM_HEIGHT = 512; static constexpr u32 VRAM_HEIGHT = 512;
static constexpr u32 VRAM_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16); static constexpr u32 VRAM_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16);

View file

@ -23,6 +23,7 @@ bool GPU_HW_OpenGL::Initialize(System* system, DMA* dma, InterruptController* in
if (!CompilePrograms()) if (!CompilePrograms())
return false; return false;
m_system->GetHostInterface()->SetDisplayTexture(m_display_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT, 1.0f);
return true; return true;
} }
@ -123,8 +124,6 @@ void GPU_HW_OpenGL::ClearFramebuffer()
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
m_system->GetHostInterface()->SetDisplayTexture(m_framebuffer_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT);
} }
void GPU_HW_OpenGL::DestroyFramebuffer() void GPU_HW_OpenGL::DestroyFramebuffer()
@ -287,7 +286,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
// TODO: 24-bit support. // TODO: 24-bit support.
if (m_show_vram) if (m_show_vram)
{ {
m_system->GetHostInterface()->SetDisplayTexture(m_framebuffer_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT); m_system->GetHostInterface()->SetDisplayTexture(m_framebuffer_texture.get(), 0, 0, VRAM_WIDTH, VRAM_HEIGHT, 1.0f);
} }
else else
{ {
@ -303,7 +302,8 @@ void GPU_HW_OpenGL::UpdateDisplay()
VRAM_HEIGHT - vram_offset_y - copy_height, 0, m_display_texture->GetGLId(), GL_TEXTURE_2D, 0, 0, VRAM_HEIGHT - vram_offset_y - copy_height, 0, m_display_texture->GetGLId(), GL_TEXTURE_2D, 0, 0,
0, 0, copy_width, copy_height, 1); 0, 0, copy_width, copy_height, 1);
m_system->GetHostInterface()->SetDisplayTexture(m_display_texture.get(), 0, 0, copy_width, copy_height); m_system->GetHostInterface()->SetDisplayTexture(m_display_texture.get(), 0, 0, copy_width, copy_height,
DISPLAY_ASPECT_RATIO);
} }
} }

View file

@ -16,7 +16,7 @@ public:
bool InitializeSystem(const char* filename, const char* exp1_filename, const char* save_state_filename); bool InitializeSystem(const char* filename, const char* exp1_filename, const char* save_state_filename);
virtual void SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height) = 0; virtual void SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height, float aspect_ratio) = 0;
virtual void ReportMessage(const char* message) = 0; virtual void ReportMessage(const char* message) = 0;
// Adds OSD messages, duration is in seconds. // Adds OSD messages, duration is in seconds.