Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correctly apply -keepaspect with -unevenstretchx/y. Initialize window… #8209

Merged
merged 3 commits into from
Jul 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 35 additions & 17 deletions src/emu/render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 2 additions & 6 deletions src/osd/sdl/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
10 changes: 3 additions & 7 deletions src/osd/windows/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down