Merge pull request #1341 from ggrtk/hostdisplay-fixes

HostDisplay: Fix some scaling issues
This commit is contained in:
Connor McLaughlin 2020-12-29 22:49:29 +10:00 committed by GitHub
commit b38e4b8ba7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 80 deletions

View file

@ -135,22 +135,23 @@ void HostDisplay::ClearSoftwareCursor()
m_cursor_texture_scale = 1.0f; m_cursor_texture_scale = 1.0f;
} }
void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, s32* out_left, s32* out_top, s32* out_width, void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, float* out_left, float* out_top,
s32* out_height, s32* out_left_padding, s32* out_top_padding, float* out_scale, float* out_width, float* out_height, float* out_left_padding,
float* out_y_scale, bool apply_aspect_ratio) const float* out_top_padding, float* out_scale, float* out_x_scale,
bool apply_aspect_ratio /* = true */) const
{ {
const float y_scale = const float x_scale =
apply_aspect_ratio ? apply_aspect_ratio ?
((static_cast<float>(m_display_width) / static_cast<float>(m_display_height)) / m_display_aspect_ratio) : (m_display_aspect_ratio / (static_cast<float>(m_display_width) / static_cast<float>(m_display_height))) :
1.0f; 1.0f;
const float display_width = static_cast<float>(m_display_width); const float display_width = static_cast<float>(m_display_width) * x_scale;
const float display_height = static_cast<float>(m_display_height) * y_scale; const float display_height = static_cast<float>(m_display_height);
const float active_left = static_cast<float>(m_display_active_left); const float active_left = static_cast<float>(m_display_active_left) * x_scale;
const float active_top = static_cast<float>(m_display_active_top) * y_scale; const float active_top = static_cast<float>(m_display_active_top);
const float active_width = static_cast<float>(m_display_active_width); const float active_width = static_cast<float>(m_display_active_width) * x_scale;
const float active_height = static_cast<float>(m_display_active_height) * y_scale; const float active_height = static_cast<float>(m_display_active_height);
if (out_y_scale) if (out_x_scale)
*out_y_scale = y_scale; *out_x_scale = x_scale;
// now fit it within the window // now fit it within the window
const float window_ratio = static_cast<float>(window_width) / static_cast<float>(window_height); const float window_ratio = static_cast<float>(window_width) / static_cast<float>(window_height);
@ -166,24 +167,25 @@ void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, s32* ou
if (out_left_padding) if (out_left_padding)
{ {
if (m_display_integer_scaling) if (m_display_integer_scaling)
*out_left_padding = std::max<s32>((window_width - static_cast<s32>(display_width * scale)) / 2, 0); *out_left_padding = std::max<float>((static_cast<float>(window_width) - display_width * scale) / 2.0f, 0.0f);
else else
*out_left_padding = 0; *out_left_padding = 0.0f;
} }
if (out_top_padding) if (out_top_padding)
{ {
switch (m_display_alignment) switch (m_display_alignment)
{ {
case Alignment::LeftOrTop: case Alignment::LeftOrTop:
*out_top_padding = 0; *out_top_padding = 0.0f;
break; break;
case Alignment::Center: case Alignment::Center:
*out_top_padding = std::max<s32>((window_height - static_cast<s32>(display_height * scale)) / 2, 0); *out_top_padding =
std::max<float>((static_cast<float>(window_height) - (display_height * scale)) / 2.0f, 0.0f);
break; break;
case Alignment::RightOrBottom: case Alignment::RightOrBottom:
*out_top_padding = std::max<s32>(window_height - static_cast<s32>(display_height * scale), 0); *out_top_padding = std::max<float>(static_cast<float>(window_height) - (display_height * scale), 0.0f);
break; break;
} }
} }
@ -200,15 +202,16 @@ void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, s32* ou
switch (m_display_alignment) switch (m_display_alignment)
{ {
case Alignment::LeftOrTop: case Alignment::LeftOrTop:
*out_left_padding = 0; *out_left_padding = 0.0f;
break; break;
case Alignment::Center: case Alignment::Center:
*out_left_padding = std::max<s32>((window_width - static_cast<s32>(display_width * scale)) / 2, 0); *out_left_padding =
std::max<float>((static_cast<float>(window_width) - (display_width * scale)) / 2.0f, 0.0f);
break; break;
case Alignment::RightOrBottom: case Alignment::RightOrBottom:
*out_left_padding = std::max<s32>(window_width - static_cast<s32>(display_width * scale), 0); *out_left_padding = std::max<float>(static_cast<float>(window_width) - (display_width * scale), 0.0f);
break; break;
} }
} }
@ -216,16 +219,16 @@ void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, s32* ou
if (out_top_padding) if (out_top_padding)
{ {
if (m_display_integer_scaling) if (m_display_integer_scaling)
*out_top_padding = std::max<s32>((window_height - static_cast<s32>(display_height * scale)) / 2, 0); *out_top_padding = std::max<float>((static_cast<float>(window_height) - (display_height * scale)) / 2.0f, 0.0f);
else else
*out_top_padding = 0; *out_top_padding = 0.0f;
} }
} }
*out_width = static_cast<s32>(active_width * scale); *out_width = active_width * scale;
*out_height = static_cast<s32>(active_height * scale); *out_height = active_height * scale;
*out_left = static_cast<s32>(active_left * scale); *out_left = active_left * scale;
*out_top = static_cast<s32>(active_top * scale); *out_top = active_top * scale;
if (out_scale) if (out_scale)
*out_scale = scale; *out_scale = scale;
} }
@ -233,10 +236,12 @@ void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, s32* ou
std::tuple<s32, s32, s32, s32> HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, s32 top_margin, std::tuple<s32, s32, s32, s32> HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, s32 top_margin,
bool apply_aspect_ratio /* = true */) const bool apply_aspect_ratio /* = true */) const
{ {
s32 left, top, width, height, left_padding, top_padding; float left, top, width, height, left_padding, top_padding;
CalculateDrawRect(window_width, window_height - top_margin, &left, &top, &width, &height, &left_padding, &top_padding, CalculateDrawRect(window_width, window_height - top_margin, &left, &top, &width, &height, &left_padding, &top_padding,
nullptr, nullptr, apply_aspect_ratio); nullptr, nullptr, apply_aspect_ratio);
return std::make_tuple(left + left_padding, top + top_padding + top_margin, width, height);
return std::make_tuple(static_cast<s32>(left + left_padding), static_cast<s32>(top + top_padding) + top_margin,
static_cast<s32>(width), static_cast<s32>(height));
} }
std::tuple<s32, s32, s32, s32> HostDisplay::CalculateSoftwareCursorDrawRect() const std::tuple<s32, s32, s32, s32> HostDisplay::CalculateSoftwareCursorDrawRect() const
@ -262,18 +267,18 @@ std::tuple<float, float> HostDisplay::ConvertWindowCoordinatesToDisplayCoordinat
s32 window_width, s32 window_height, s32 window_width, s32 window_height,
s32 top_margin) const s32 top_margin) const
{ {
s32 left, top, width, height, left_padding, top_padding; float left, top, width, height, left_padding, top_padding;
float scale, y_scale; float scale, x_scale;
CalculateDrawRect(window_width, window_height - top_margin, &left, &top, &width, &height, &left_padding, &top_padding, CalculateDrawRect(window_width, window_height - top_margin, &left, &top, &width, &height, &left_padding, &top_padding,
&scale, &y_scale); &scale, &x_scale);
// convert coordinates to active display region, then to full display region // convert coordinates to active display region, then to full display region
const float scaled_display_x = static_cast<float>(window_x - (left_padding)); const float scaled_display_x = static_cast<float>(window_x) - left_padding;
const float scaled_display_y = static_cast<float>(window_y - (top_padding + top_margin)); const float scaled_display_y = static_cast<float>(window_y) - top_padding + static_cast<float>(top_margin);
// scale back to internal resolution // scale back to internal resolution
const float display_x = scaled_display_x / scale; const float display_x = scaled_display_x / scale / x_scale;
const float display_y = scaled_display_y / scale / y_scale; const float display_y = scaled_display_y / scale;
return std::make_tuple(display_x, display_y); return std::make_tuple(display_x, display_y);
} }
@ -486,52 +491,29 @@ bool HostDisplay::WriteDisplayTextureToFile(std::string filename, bool full_reso
if (!m_display_texture_handle) if (!m_display_texture_handle)
return false; return false;
apply_aspect_ratio = (m_display_aspect_ratio > 0) ? apply_aspect_ratio : false;
s32 resize_width = 0; s32 resize_width = 0;
s32 resize_height = 0; s32 resize_height = std::abs(m_display_texture_view_height);
if (apply_aspect_ratio && full_resolution) if (apply_aspect_ratio)
{ {
if (m_display_aspect_ratio > 1.0f) const float ss_width_scale = static_cast<float>(m_display_active_width) / static_cast<float>(m_display_width);
const float ss_height_scale = static_cast<float>(m_display_active_height) / static_cast<float>(m_display_height);
const float ss_aspect_ratio = m_display_aspect_ratio * ss_width_scale / ss_height_scale;
resize_width = static_cast<s32>(static_cast<float>(resize_height) * ss_aspect_ratio);
}
else
{ {
resize_width = m_display_texture_view_width; resize_width = m_display_texture_view_width;
resize_height = static_cast<s32>(static_cast<float>(resize_width) / m_display_aspect_ratio);
}
else
{
resize_height = std::abs(m_display_texture_view_height);
resize_width = static_cast<s32>(static_cast<float>(resize_height) * m_display_aspect_ratio);
}
}
else if (apply_aspect_ratio)
{
const auto [left, top, right, bottom] =
CalculateDrawRect(GetWindowWidth(), GetWindowHeight(), m_display_top_margin);
resize_width = right - left;
resize_height = bottom - top;
}
else if (!full_resolution)
{
const auto [left, top, right, bottom] =
CalculateDrawRect(GetWindowWidth(), GetWindowHeight(), m_display_top_margin);
const float ratio =
static_cast<float>(m_display_texture_view_width) / static_cast<float>(std::abs(m_display_texture_view_height));
if (ratio > 1.0f)
{
resize_width = right - left;
resize_height = static_cast<s32>(static_cast<float>(resize_width) / ratio);
}
else
{
resize_height = bottom - top;
resize_width = static_cast<s32>(static_cast<float>(resize_height) * ratio);
}
} }
if (resize_width < 0) if (!full_resolution)
resize_width = 1; {
if (resize_height < 0) const s32 resolution_scale = std::abs(m_display_texture_view_height) / m_display_active_height;
resize_height = 1; resize_height /= resolution_scale;
resize_width /= resolution_scale;
}
if (resize_width <= 0 || resize_height <= 0)
return false;
const bool flip_y = (m_display_texture_view_height < 0); const bool flip_y = (m_display_texture_view_height < 0);
s32 read_height = m_display_texture_view_height; s32 read_height = m_display_texture_view_height;

View file

@ -213,9 +213,9 @@ protected:
ALWAYS_INLINE bool HasSoftwareCursor() const { return static_cast<bool>(m_cursor_texture); } ALWAYS_INLINE bool HasSoftwareCursor() const { return static_cast<bool>(m_cursor_texture); }
ALWAYS_INLINE bool HasDisplayTexture() const { return (m_display_texture_handle != nullptr); } ALWAYS_INLINE bool HasDisplayTexture() const { return (m_display_texture_handle != nullptr); }
void CalculateDrawRect(s32 window_width, s32 window_height, s32* out_left, s32* out_top, s32* out_width, void CalculateDrawRect(s32 window_width, s32 window_height, float* out_left, float* out_top, float* out_width,
s32* out_height, s32* out_left_padding, s32* out_top_padding, float* out_scale, float* out_height, float* out_left_padding, float* out_top_padding, float* out_scale,
float* out_y_scale, bool apply_aspect_ratio = true) const; float* out_x_scale, bool apply_aspect_ratio = true) const;
std::tuple<s32, s32, s32, s32> CalculateSoftwareCursorDrawRect() const; std::tuple<s32, s32, s32, s32> CalculateSoftwareCursorDrawRect() const;
std::tuple<s32, s32, s32, s32> CalculateSoftwareCursorDrawRect(s32 cursor_x, s32 cursor_y) const; std::tuple<s32, s32, s32, s32> CalculateSoftwareCursorDrawRect(s32 cursor_x, s32 cursor_y) const;

View file

@ -1006,7 +1006,7 @@ void VulkanHostDisplay::ApplyPostProcessingChain(s32 final_left, s32 final_top,
Assert(pps.uniforms_size <= sizeof(buffer)); Assert(pps.uniforms_size <= sizeof(buffer));
m_post_processing_chain.GetShaderStage(i).FillUniformBuffer( m_post_processing_chain.GetShaderStage(i).FillUniformBuffer(
buffer, texture_width, texture_height, texture_view_x, texture_view_y, texture_view_width, texture_view_height, buffer, texture_width, texture_height, texture_view_x, texture_view_y, texture_view_width, texture_view_height,
texture_width, texture_width, 0.0f); GetWindowWidth(), GetWindowHeight(), 0.0f);
vkCmdPushConstants(cmdbuffer, m_post_process_pipeline_layout, vkCmdPushConstants(cmdbuffer, m_post_process_pipeline_layout,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, pps.uniforms_size, buffer); VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, pps.uniforms_size, buffer);