mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
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.
This commit is contained in:
parent
b59ede5db0
commit
5186eaaff1
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user