GPU: Implement "Crop Mode" (none, overscan, all borders)

This commit is contained in:
Connor McLaughlin
2020-02-28 17:01:01 +10:00
parent 5df7fbd68c
commit fcc0ae9571
28 changed files with 491 additions and 337 deletions

View File

@ -102,6 +102,30 @@ void D3D11HostDisplay::ChangeRenderWindow(void* new_window)
Panic("Not supported");
}
void D3D11HostDisplay::WindowResized(s32 new_window_width, s32 new_window_height)
{
HostDisplay::WindowResized(new_window_width, new_window_height);
m_swap_chain_rtv.Reset();
HRESULT hr = m_swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN,
m_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
if (FAILED(hr))
Log_ErrorPrintf("ResizeBuffers() failed: 0x%08X", hr);
if (!CreateSwapChainRTV())
Panic("Failed to recreate swap chain RTV after resize");
DXGI_SWAP_CHAIN_DESC desc;
if (SUCCEEDED(m_swap_chain->GetDesc(&desc)))
{
m_window_width = static_cast<int>(desc.BufferDesc.Width);
m_window_height = static_cast<int>(desc.BufferDesc.Height);
ImGui::GetIO().DisplaySize.x = static_cast<float>(m_window_width);
ImGui::GetIO().DisplaySize.y = static_cast<float>(m_window_height);
}
}
std::unique_ptr<HostDisplayTexture> D3D11HostDisplay::CreateTexture(u32 width, u32 height, const void* data,
u32 data_stride, bool dynamic)
{
@ -149,33 +173,6 @@ void D3D11HostDisplay::SetVSync(bool enabled)
m_vsync = enabled;
}
std::tuple<u32, u32> D3D11HostDisplay::GetWindowSize() const
{
return std::make_tuple(static_cast<u32>(m_window_width), static_cast<u32>(m_window_height));
}
void D3D11HostDisplay::WindowResized()
{
m_swap_chain_rtv.Reset();
HRESULT hr = m_swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN,
m_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
if (FAILED(hr))
Log_ErrorPrintf("ResizeBuffers() failed: 0x%08X", hr);
if (!CreateSwapChainRTV())
Panic("Failed to recreate swap chain RTV after resize");
DXGI_SWAP_CHAIN_DESC desc;
if (SUCCEEDED(m_swap_chain->GetDesc(&desc)))
{
m_window_width = static_cast<int>(desc.BufferDesc.Width);
m_window_height = static_cast<int>(desc.BufferDesc.Height);
ImGui::GetIO().DisplaySize.x = static_cast<float>(m_window_width);
ImGui::GetIO().DisplaySize.y = static_cast<float>(m_window_height);
}
}
bool D3D11HostDisplay::CreateD3DDevice(bool debug_device)
{
SDL_SysWMinfo syswm = {};
@ -388,10 +385,7 @@ void D3D11HostDisplay::RenderDisplay()
if (!m_display_texture_handle)
return;
// - 20 for main menu padding
auto [vp_left, vp_top, vp_width, vp_height] =
CalculateDrawRect(m_window_width, std::max(m_window_height - m_display_top_margin, 1), m_display_aspect_ratio);
vp_top += m_display_top_margin;
const auto [vp_left, vp_top, vp_width, vp_height] = CalculateDrawRect();
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_context->VSSetShader(m_display_vertex_shader.Get(), nullptr, 0);
@ -400,11 +394,11 @@ void D3D11HostDisplay::RenderDisplay()
m_context->PSSetSamplers(
0, 1, m_display_linear_filtering ? m_linear_sampler.GetAddressOf() : m_point_sampler.GetAddressOf());
const float uniforms[4] = {static_cast<float>(m_display_offset_x) / static_cast<float>(m_display_texture_width),
static_cast<float>(m_display_offset_y) / static_cast<float>(m_display_texture_height),
(static_cast<float>(m_display_width) - 0.5f) / static_cast<float>(m_display_texture_width),
(static_cast<float>(m_display_height) - 0.5f) /
static_cast<float>(m_display_texture_height)};
const float uniforms[4] = {
static_cast<float>(m_display_texture_rect.left) / static_cast<float>(m_display_texture_width),
static_cast<float>(m_display_texture_rect.top) / static_cast<float>(m_display_texture_height),
(static_cast<float>(m_display_texture_rect.GetWidth()) - 0.5f) / static_cast<float>(m_display_texture_width),
(static_cast<float>(m_display_texture_rect.GetHeight()) - 0.5f) / static_cast<float>(m_display_texture_height)};
const auto map = m_display_uniform_buffer.Map(m_context.Get(), sizeof(uniforms), sizeof(uniforms));
std::memcpy(map.pointer, uniforms, sizeof(uniforms));
m_display_uniform_buffer.Unmap(m_context.Get(), sizeof(uniforms));

View File

@ -25,6 +25,7 @@ public:
void* GetRenderWindow() const override;
void ChangeRenderWindow(void* new_window) override;
void WindowResized(s32 new_window_width, s32 new_window_height) override;
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* data, u32 data_stride,
bool dynamic) override;
@ -33,9 +34,6 @@ public:
void SetVSync(bool enabled) override;
std::tuple<u32, u32> GetWindowSize() const override;
void WindowResized() override;
private:
static constexpr u32 DISPLAY_UNIFORM_BUFFER_SIZE = 16;
@ -49,8 +47,6 @@ private:
SDL_Window* m_window = nullptr;
SDL_GLContext m_gl_context = nullptr;
int m_window_width = 0;
int m_window_height = 0;
ComPtr<ID3D11Device> m_device;
ComPtr<ID3D11DeviceContext> m_context;

View File

@ -77,7 +77,7 @@ int main(int argc, char* argv[])
Log::SetFilterLevel(level);
#else
Log::SetConsoleOutputParams(true, nullptr, LOGLEVEL_DEBUG);
// Log::SetConsoleOutputParams(true, "Pad DigitalController MemoryCard", LOGLEVEL_DEBUG);
Log::SetConsoleOutputParams(true, "Pad DigitalController MemoryCard SPU", LOGLEVEL_DEBUG);
// Log::SetConsoleOutputParams(true, "GPU GPU_HW_OpenGL SPU Pad DigitalController", LOGLEVEL_DEBUG);
// Log::SetConsoleOutputParams(true, "GPU GPU_HW_OpenGL Pad DigitalController MemoryCard InterruptController SPU
// MDEC", LOGLEVEL_DEBUG); g_pLog->SetFilterLevel(LOGLEVEL_TRACE);

View File

@ -100,6 +100,14 @@ void OpenGLHostDisplay::ChangeRenderWindow(void* new_window)
Panic("Not implemented");
}
void OpenGLHostDisplay::WindowResized(s32 new_window_width, s32 new_window_height)
{
HostDisplay::WindowResized(new_window_width, new_window_height);
SDL_GL_GetDrawableSize(m_window, &m_window_width, &m_window_height);
ImGui::GetIO().DisplaySize.x = static_cast<float>(m_window_width);
ImGui::GetIO().DisplaySize.y = static_cast<float>(m_window_height);
}
std::unique_ptr<HostDisplayTexture> OpenGLHostDisplay::CreateTexture(u32 width, u32 height, const void* data,
u32 data_stride, bool dynamic)
{
@ -131,18 +139,6 @@ void OpenGLHostDisplay::SetVSync(bool enabled)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_fbo);
}
std::tuple<u32, u32> OpenGLHostDisplay::GetWindowSize() const
{
return std::make_tuple(static_cast<u32>(m_window_width), static_cast<u32>(m_window_height));
}
void OpenGLHostDisplay::WindowResized()
{
SDL_GL_GetDrawableSize(m_window, &m_window_width, &m_window_height);
ImGui::GetIO().DisplaySize.x = static_cast<float>(m_window_width);
ImGui::GetIO().DisplaySize.y = static_cast<float>(m_window_height);
}
const char* OpenGLHostDisplay::GetGLSLVersionString() const
{
if (m_is_gles)
@ -380,11 +376,9 @@ void OpenGLHostDisplay::RenderDisplay()
if (!m_display_texture_handle)
return;
// - 20 for main menu padding
const auto [vp_left, vp_top, vp_width, vp_height] =
CalculateDrawRect(m_window_width, std::max(m_window_height - m_display_top_margin, 1), m_display_aspect_ratio);
const auto [vp_left, vp_top, vp_width, vp_height] = CalculateDrawRect();
glViewport(vp_left, m_window_height - (m_display_top_margin + vp_top) - vp_height, vp_width, vp_height);
glViewport(vp_left, m_window_height - vp_top - vp_height, vp_width, vp_height);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
@ -392,10 +386,10 @@ void OpenGLHostDisplay::RenderDisplay()
glDepthMask(GL_FALSE);
m_display_program.Bind();
m_display_program.Uniform4f(
0, static_cast<float>(m_display_offset_x) / static_cast<float>(m_display_texture_width),
static_cast<float>(m_display_offset_y) / static_cast<float>(m_display_texture_height),
(static_cast<float>(m_display_width) - 0.5f) / static_cast<float>(m_display_texture_width),
(static_cast<float>(m_display_height) - 0.5f) / static_cast<float>(m_display_texture_height));
0, static_cast<float>(m_display_texture_rect.left) / static_cast<float>(m_display_texture_width),
static_cast<float>(m_display_texture_rect.top) / static_cast<float>(m_display_texture_height),
(static_cast<float>(m_display_texture_rect.GetWidth()) - 0.5f) / static_cast<float>(m_display_texture_width),
(static_cast<float>(m_display_texture_rect.GetHeight()) - 0.5f) / static_cast<float>(m_display_texture_height));
glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(reinterpret_cast<uintptr_t>(m_display_texture_handle)));
glBindSampler(0, m_display_linear_filtering ? m_display_linear_sampler : m_display_nearest_sampler);
glBindVertexArray(m_display_vao);

View File

@ -20,6 +20,7 @@ public:
void* GetRenderWindow() const override;
void ChangeRenderWindow(void* new_window) override;
void WindowResized(s32 new_window_width, s32 new_window_height) override;
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* data, u32 data_stride,
bool dynamic) override;
@ -28,9 +29,6 @@ public:
void SetVSync(bool enabled) override;
std::tuple<u32, u32> GetWindowSize() const override;
void WindowResized() override;
private:
const char* GetGLSLVersionString() const;
std::string GetGLSLVersionHeader() const;
@ -44,8 +42,6 @@ private:
SDL_Window* m_window = nullptr;
SDL_GLContext m_gl_context = nullptr;
int m_window_width = 0;
int m_window_height = 0;
GL::Program m_display_program;
GLuint m_display_vao = 0;

View File

@ -287,7 +287,9 @@ void SDLHostInterface::SetFullscreen(bool enabled)
// We set the margin only in windowed mode, the menu bar is drawn on top in fullscreen.
m_display->SetDisplayTopMargin(enabled ? 0 : static_cast<int>(20.0f * ImGui::GetIO().DisplayFramebufferScale.x));
m_display->WindowResized();
int window_width, window_height;
SDL_GetWindowSize(m_window, &window_width, &window_height);
m_display->WindowResized(window_width, window_height);
m_fullscreen = enabled;
}
@ -371,7 +373,7 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
{
if (event->window.event == SDL_WINDOWEVENT_RESIZED)
{
m_display->WindowResized();
m_display->WindowResized(event->window.data1, event->window.data2);
UpdateFramebufferScale();
}
else if (event->window.event == SDL_WINDOWEVENT_MOVED)
@ -1221,6 +1223,22 @@ void SDLHostInterface::DrawSettingsWindow()
if (DrawSettingsSectionHeader("Display Output"))
{
ImGui::Text("Crop:");
ImGui::SameLine(indent);
int display_crop_mode = static_cast<int>(m_settings_copy.display_crop_mode);
if (ImGui::Combo(
"##display_crop_mode", &display_crop_mode,
[](void*, int index, const char** out_text) {
*out_text = Settings::GetDisplayCropModeDisplayName(static_cast<DisplayCropMode>(index));
return true;
},
nullptr, static_cast<int>(DisplayCropMode::Count)))
{
m_settings_copy.display_crop_mode = static_cast<DisplayCropMode>(display_crop_mode);
settings_changed = true;
}
if (ImGui::Checkbox("Start Fullscreen", &m_settings_copy.display_fullscreen))
settings_changed = true;
@ -1265,7 +1283,7 @@ void SDLHostInterface::DrawSettingsWindow()
settings_changed |= ImGui::Checkbox("True 24-bit Color (disables dithering)", &m_settings_copy.gpu_true_color);
settings_changed |= ImGui::Checkbox("Texture Filtering", &m_settings_copy.gpu_texture_filtering);
settings_changed |= ImGui::Checkbox("Force Progressive Scan", &m_settings_copy.gpu_force_progressive_scan);
settings_changed |= ImGui::Checkbox("Force Progressive Scan", &m_settings_copy.display_force_progressive_scan);
}
ImGui::EndTabItem();