From 5186eaaff1a10d981f75a8d49cf1096ff2159356 Mon Sep 17 00:00:00 2001 From: antonioginer Date: Fri, 2 Jul 2021 12:07:21 +0200 Subject: Correctly apply -keepaspect with -unevenstretchx/y. (#8209) * Correctly apply -keepaspect with -unevenstretchx/y. Initialize window at the correct size when -intscalex/y is used. * Get correct window size upon maximizing/minimizing with integer scaling. --- src/emu/render.cpp | 52 +++++++++++++++++++++++++++++++--------------- src/osd/sdl/window.cpp | 8 ++----- src/osd/windows/window.cpp | 10 +++------ 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/emu/render.cpp b/src/emu/render.cpp index b7a66b7bd2a..9862b0e35db 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -1193,37 +1193,55 @@ void render_target::compute_visible_area(s32 target_width, s32 target_height, fl // get target aspect float target_aspect = (float)target_width / (float)target_height * target_pixel_aspect; - bool target_is_portrait = (target_aspect < 1.0f); // apply automatic axial stretching if required int scale_mode = m_scale_mode; if (m_scale_mode == SCALE_FRACTIONAL_AUTO) { bool is_rotated = (m_manager.machine().system().flags & ORIENTATION_SWAP_XY) ^ (target_orientation & ORIENTATION_SWAP_XY); - scale_mode = is_rotated ^ target_is_portrait ? SCALE_FRACTIONAL_Y : SCALE_FRACTIONAL_X; + scale_mode = is_rotated ? SCALE_FRACTIONAL_Y : SCALE_FRACTIONAL_X; } - // determine the scale mode for each axis - bool x_is_integer = !((!target_is_portrait && scale_mode == SCALE_FRACTIONAL_X) || (target_is_portrait && scale_mode == SCALE_FRACTIONAL_Y)); - bool y_is_integer = !((target_is_portrait && scale_mode == SCALE_FRACTIONAL_X) || (!target_is_portrait && scale_mode == SCALE_FRACTIONAL_Y)); - // first compute scale factors to fit the screen float xscale = (float)target_width / src_width; float yscale = (float)target_height / src_height; - float maxxscale = std::max(1.0f, float(m_int_overscan ? render_round_nearest(xscale) : floor(xscale))); - float maxyscale = std::max(1.0f, float(m_int_overscan ? render_round_nearest(yscale) : floor(yscale))); - // now apply desired scale mode and aspect correction - if (m_keepaspect && target_aspect > src_aspect) xscale *= src_aspect / target_aspect * (maxyscale / yscale); - if (m_keepaspect && target_aspect < src_aspect) yscale *= target_aspect / src_aspect * (maxxscale / xscale); - if (x_is_integer) xscale = std::clamp(render_round_nearest(xscale), 1.0f, maxxscale); - if (y_is_integer) yscale = std::clamp(render_round_nearest(yscale), 1.0f, maxyscale); + // apply aspect correction + if (m_keepaspect) + { + if (target_aspect > src_aspect) + xscale *= src_aspect / target_aspect; + else + yscale *= target_aspect / src_aspect; + } + + bool x_fits = render_round_nearest(xscale) * src_width <= target_width; + bool y_fits = render_round_nearest(yscale) * src_height <= target_height; + + // compute integer scale factors + float integer_x = std::max(1.0f, float(m_int_overscan || x_fits ? render_round_nearest(xscale) : floor(xscale))); + float integer_y = std::max(1.0f, float(m_int_overscan || y_fits ? render_round_nearest(yscale) : floor(yscale))); // check if we have user defined scale factors, if so use them instead - int user_scale_x = target_is_portrait? m_int_scale_y : m_int_scale_x; - int user_scale_y = target_is_portrait? m_int_scale_x : m_int_scale_y; - xscale = user_scale_x > 0 ? user_scale_x : xscale; - yscale = user_scale_y > 0 ? user_scale_y : yscale; + integer_x = m_int_scale_x > 0 ? m_int_scale_x : integer_x; + integer_y = m_int_scale_y > 0 ? m_int_scale_y : integer_y; + + // now apply desired scale mode + if (scale_mode == SCALE_FRACTIONAL_X) + { + if (m_keepaspect) xscale *= integer_y / yscale; + yscale = integer_y; + } + else if (scale_mode == SCALE_FRACTIONAL_Y) + { + if (m_keepaspect) yscale *= integer_x / xscale; + xscale = integer_x; + } + else + { + xscale = integer_x; + yscale = integer_y; + } // set the final width/height visible_width = render_round_nearest(src_width * xscale); diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp index 0d15c4e4c0b..29ed4b920eb 100644 --- a/src/osd/sdl/window.cpp +++ b/src/osd/sdl/window.cpp @@ -904,10 +904,6 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad int32_t adjwidth, adjheight; float pixel_aspect; - // do not constrain aspect ratio for integer scaled views - if (target()->scale_mode() != SCALE_FRACTIONAL) - return rect; - // get the pixel aspect ratio for the target monitor pixel_aspect = monitor()->pixel_aspect(); @@ -1029,7 +1025,7 @@ osd_dim sdl_window_info::get_min_bounds(int constrain) minheight += wnd_extra_height(); // if we want it constrained, figure out which one is larger - if (constrain && target()->scale_mode() == SCALE_FRACTIONAL) + if (constrain) { // first constrain with no height limit osd_rect test1(0,0,minwidth,10000); @@ -1103,7 +1099,7 @@ osd_dim sdl_window_info::get_max_bounds(int constrain) maximum = maximum.resize(tempw, temph); // constrain to fit - if (constrain && target()->scale_mode() == SCALE_FRACTIONAL) + if (constrain) maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT); // remove extra window stuff diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp index cc9ff4484ba..ec549933956 100644 --- a/src/osd/windows/window.cpp +++ b/src/osd/windows/window.cpp @@ -1236,7 +1236,7 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR case WM_SIZING: { RECT *rect = (RECT *)lparam; - if (window->keepaspect() && !(GetAsyncKeyState(VK_CONTROL) & 0x8000)) + if (window->keepaspect() && (window->target()->scale_mode() == SCALE_FRACTIONAL) && !(GetAsyncKeyState(VK_CONTROL) & 0x8000)) { osd_rect r = window->constrain_to_aspect_ratio(RECT_to_osd_rect(*rect), wparam); rect->top = r.top(); @@ -1422,10 +1422,6 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad if (monitor == nullptr) return rect; - // do not constrain aspect ratio for integer scaled views - if (target()->scale_mode() != SCALE_FRACTIONAL) - return rect; - // get the pixel aspect ratio for the target monitor pixel_aspect = monitor->pixel_aspect(); @@ -1551,7 +1547,7 @@ osd_dim win_window_info::get_min_bounds(int constrain) minheight += wnd_extra_height(); // if we want it constrained, figure out which one is larger - if (constrain && target()->scale_mode() == SCALE_FRACTIONAL) + if (constrain) { // first constrain with no height limit osd_rect test1(0,0,minwidth,10000); @@ -1611,7 +1607,7 @@ osd_dim win_window_info::get_max_bounds(int constrain) maximum = maximum.resize(tempw, temph); // constrain to fit - if (constrain && target()->scale_mode() == SCALE_FRACTIONAL) + if (constrain) maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT); return maximum.dim(); -- cgit v1.2.3