diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp index f8127e28dbb..35a8fae6333 100644 --- a/src/emu/emuopts.cpp +++ b/src/emu/emuopts.cpp @@ -88,6 +88,14 @@ const options_entry emu_options::s_option_entries[] = { OPTION_SPEED "(0.01-100)", "1.0", OPTION_FLOAT, "controls the speed of gameplay, relative to realtime; smaller numbers are slower" }, { OPTION_REFRESHSPEED ";rs", "0", OPTION_BOOLEAN, "automatically adjusts the speed of gameplay to keep the refresh rate lower than the screen" }, + // render options + { nullptr, nullptr, OPTION_HEADER, "CORE RENDER OPTIONS" }, + { OPTION_KEEPASPECT ";ka", "1", OPTION_BOOLEAN, "constrain to the proper aspect ratio" }, + { OPTION_UNEVENSTRETCH ";ues", "1", OPTION_BOOLEAN, "allow non-integer stretch factors" }, + { OPTION_UNEVENSTRETCHX ";uesx", "0", OPTION_BOOLEAN, "allow non-integer stretch factors only on horizontal axis"}, + { OPTION_INTSCALEX ";sx", "0", OPTION_INTEGER, "set horizontal integer scale factor."}, + { OPTION_INTSCALEY ";sy", "0", OPTION_INTEGER, "set vertical integer scale."}, + // rotation options { nullptr, nullptr, OPTION_HEADER, "CORE ROTATION OPTIONS" }, { OPTION_ROTATE, "1", OPTION_BOOLEAN, "rotate the game screen according to the game's orientation needs it" }, diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h index 0512924dd59..a85c7485406 100644 --- a/src/emu/emuopts.h +++ b/src/emu/emuopts.h @@ -98,6 +98,13 @@ enum #define OPTION_SPEED "speed" #define OPTION_REFRESHSPEED "refreshspeed" +// core render options +#define OPTION_KEEPASPECT "keepaspect" +#define OPTION_UNEVENSTRETCH "unevenstretch" +#define OPTION_UNEVENSTRETCHX "unevenstretchx" +#define OPTION_INTSCALEX "intscalex" +#define OPTION_INTSCALEY "intscaley" + // core rotation options #define OPTION_ROTATE "rotate" #define OPTION_ROR "ror" @@ -282,6 +289,13 @@ public: float speed() const { return float_value(OPTION_SPEED); } bool refresh_speed() const { return m_refresh_speed; } + // core render options + bool keep_aspect() const { return bool_value(OPTION_KEEPASPECT); } + bool uneven_stretch() const { return bool_value(OPTION_UNEVENSTRETCH); } + bool uneven_stretch_x() const { return bool_value(OPTION_UNEVENSTRETCHX); } + int int_scale_x() const { return int_value(OPTION_INTSCALEX); } + int int_scale_y() const { return int_value(OPTION_INTSCALEY); } + // core rotation options bool rotate() const { return bool_value(OPTION_ROTATE); } bool ror() const { return bool_value(OPTION_ROR); } diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 806921f8981..f47704050b5 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -931,6 +931,15 @@ render_target::render_target(render_manager &manager, const char *layoutfile, UI m_base_layerconfig.set_marquees_enabled(manager.machine().options().use_marquees()); m_base_layerconfig.set_zoom_to_screen(manager.machine().options().artwork_crop()); + // aspect and scale options + m_keepaspect = manager.machine().options().keep_aspect(); + m_int_scale_x = manager.machine().options().int_scale_x(); + m_int_scale_y = manager.machine().options().int_scale_y(); + if (manager.machine().options().uneven_stretch() && !manager.machine().options().uneven_stretch_x()) + m_scale_mode = SCALE_FRACTIONAL; + else + m_scale_mode = manager.machine().options().uneven_stretch_x()? SCALE_FRACTIONAL_X : SCALE_INTEGER; + // determine the base orientation based on options if (!manager.machine().options().rotate()) m_base_orientation = orientation_reverse(manager.machine().system().flags & ORIENTATION_MASK); @@ -1005,7 +1014,7 @@ void render_target::set_bounds(INT32 width, INT32 height, float pixel_aspect) m_bounds.x0 = m_bounds.y0 = 0; m_bounds.x1 = (float)width; m_bounds.y1 = (float)height; - m_pixel_aspect = pixel_aspect; + m_pixel_aspect = pixel_aspect != 0.0? pixel_aspect : 1.0; } @@ -1140,41 +1149,87 @@ const render_screen_list &render_target::view_screens(int viewindex) void render_target::compute_visible_area(INT32 target_width, INT32 target_height, float target_pixel_aspect, int target_orientation, INT32 &visible_width, INT32 &visible_height) { - float width, height; - float scale; - - // constrained case - if (target_pixel_aspect != 0.0f) + switch (m_scale_mode) { - // start with the aspect ratio of the square pixel layout - width = m_curview->effective_aspect(m_layerconfig); - height = 1.0f; + case SCALE_FRACTIONAL: + { + float width, height; + float scale; - // first apply target orientation - if (target_orientation & ORIENTATION_SWAP_XY) - FSWAP(width, height); + // constrained case + if (m_keepaspect) + { + // start with the aspect ratio of the square pixel layout + width = m_curview->effective_aspect(m_layerconfig); + height = 1.0f; - // apply the target pixel aspect ratio - height *= target_pixel_aspect; + // first apply target orientation + if (target_orientation & ORIENTATION_SWAP_XY) + FSWAP(width, height); - // based on the height/width ratio of the source and target, compute the scale factor - if (width / height > (float)target_width / (float)target_height) - scale = (float)target_width / width; - else - scale = (float)target_height / height; + // apply the target pixel aspect ratio + height *= target_pixel_aspect; + + // based on the height/width ratio of the source and target, compute the scale factor + if (width / height > (float)target_width / (float)target_height) + scale = (float)target_width / width; + else + scale = (float)target_height / height; + } + + // stretch-to-fit case + else + { + width = (float)target_width; + height = (float)target_height; + scale = 1.0f; + } + + // set the final width/height + visible_width = render_round_nearest(width * scale); + visible_height = render_round_nearest(height * scale); + break; + } + + case SCALE_FRACTIONAL_X: + case SCALE_INTEGER: + { + // get source size and aspect + INT32 src_width, src_height; + compute_minimum_size(src_width, src_height); + float src_aspect = m_curview->effective_aspect(m_layerconfig); + + // apply orientation if required + if (target_orientation & ORIENTATION_SWAP_XY) + src_aspect = 1.0 / src_aspect; + + // get destination size and aspect + float dest_width = (float)target_width; + float dest_height = (float)target_height; + float dest_aspect = dest_width / dest_height * target_pixel_aspect; + + // apply aspect correction to destination rectangle + if (dest_aspect > src_aspect) + dest_width *= m_keepaspect? src_aspect / dest_aspect : 1.0f; + else + dest_height *= m_keepaspect? dest_aspect / src_aspect : 1.0f; + + // compute scale factors + float xscale = dest_width / src_width; + float yscale = dest_height / src_height; + xscale = dest_aspect >= 1.0f && m_scale_mode == SCALE_FRACTIONAL_X? xscale : MAX(1, render_round_nearest(xscale)); + yscale = dest_aspect < 1.0f && m_scale_mode == SCALE_FRACTIONAL_X? yscale : MAX(1, render_round_nearest(yscale)); + + // check if we have user defined scale factors, if so use them instead + xscale = m_int_scale_x? m_int_scale_x : xscale; + yscale = m_int_scale_y? m_int_scale_y : yscale; + + // set the final width/height + visible_width = render_round_nearest(src_width * xscale); + visible_height = render_round_nearest(src_height * yscale); + break; + } } - - // stretch-to-fit case - else - { - width = (float)target_width; - height = (float)target_height; - scale = 1.0f; - } - - // set the final width/height - visible_width = render_round_nearest(width * scale); - visible_height = render_round_nearest(height * scale); } @@ -2528,7 +2583,7 @@ float render_manager::ui_aspect(render_container *rc) // if we have a valid pixel aspect, apply that and return if (m_ui_target->pixel_aspect() != 0.0f) - return (aspect / m_ui_target->pixel_aspect()); + aspect /= m_ui_target->pixel_aspect(); } else { // single screen container diff --git a/src/emu/render.h b/src/emu/render.h index 09fe68282ef..84fc3b95fdf 100644 --- a/src/emu/render.h +++ b/src/emu/render.h @@ -73,6 +73,13 @@ const UINT8 RENDER_CREATE_NO_ART = 0x01; // ignore any views that const UINT8 RENDER_CREATE_SINGLE_FILE = 0x02; // only load views from the file specified const UINT8 RENDER_CREATE_HIDDEN = 0x04; // don't make this target visible +// render scaling modes +enum +{ + SCALE_FRACTIONAL = 0, // compute fractional scaling factors for both axes + SCALE_FRACTIONAL_X, // compute fractional scaling factor for x-axis, and integer factor for y-axis + SCALE_INTEGER // compute integer scaling factors for both axes, based on target dimensions +}; // flags for primitives const int PRIMFLAG_TEXORIENT_SHIFT = 0; @@ -86,7 +93,6 @@ const UINT32 PRIMFLAG_BLENDMODE_MASK = 15 << PRIMFLAG_BLENDMODE_SHIFT; const int PRIMFLAG_ANTIALIAS_SHIFT = 12; const UINT32 PRIMFLAG_ANTIALIAS_MASK = 1 << PRIMFLAG_ANTIALIAS_SHIFT; - const int PRIMFLAG_SCREENTEX_SHIFT = 13; const UINT32 PRIMFLAG_SCREENTEX_MASK = 1 << PRIMFLAG_SCREENTEX_SHIFT; @@ -892,6 +898,7 @@ public: UINT32 width() const { return m_width; } UINT32 height() const { return m_height; } float pixel_aspect() const { return m_pixel_aspect; } + int scale_mode() const { return m_scale_mode; } float max_update_rate() const { return m_max_refresh; } int orientation() const { return m_orientation; } render_layer_config layer_config() const { return m_layerconfig; } @@ -994,7 +1001,11 @@ private: INT32 m_width; // width in pixels INT32 m_height; // height in pixels render_bounds m_bounds; // bounds of the target + bool m_keepaspect; // constrain aspect ratio float m_pixel_aspect; // aspect ratio of individual pixels + int m_scale_mode; // type of scale to apply + int m_int_scale_x; // horizontal integer scale factor + int m_int_scale_y; // vertical integer scale factor float m_max_refresh; // maximum refresh rate, 0 or if none int m_orientation; // orientation render_layer_config m_layerconfig; // layer configuration diff --git a/src/emu/ui/dsplmenu.cpp b/src/emu/ui/dsplmenu.cpp index 5ee2bfd0ca2..d0d308d3bb9 100644 --- a/src/emu/ui/dsplmenu.cpp +++ b/src/emu/ui/dsplmenu.cpp @@ -37,7 +37,6 @@ ui_menu_display_options::dspl_option ui_menu_display_options::m_options[] = { { 0, nullptr, nullptr }, { 0, __("Video Mode"), OSDOPTION_VIDEO }, #if defined(UI_WINDOWS) && !defined(UI_SDL) - { 0, __("Hardware Stretch"), WINOPTION_HWSTRETCH }, { 0, __("Triple Buffering"), WINOPTION_TRIPLEBUFFER }, { 0, __("HLSL"), WINOPTION_HLSL_ENABLE }, #endif @@ -46,7 +45,7 @@ ui_menu_display_options::dspl_option ui_menu_display_options::m_options[] = { { 0, __("Bitmap Prescaling"), OSDOPTION_PRESCALE }, { 0, __("Multi-Threaded Rendering"), OSDOPTION_MULTITHREADING }, { 0, __("Window Mode"), OSDOPTION_WINDOW }, - { 0, __("Enforce Aspect Ratio"), OSDOPTION_KEEPASPECT }, + { 0, __("Enforce Aspect Ratio"), OPTION_KEEPASPECT }, { 0, __("Start Out Maximized"), OSDOPTION_MAXIMIZE }, { 0, __("Synchronized Refresh"), OSDOPTION_SYNCREFRESH }, { 0, __("Wait Vertical Sync"), OSDOPTION_WAITVSYNC } diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index 30c77a12211..100b8bba0c8 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -52,8 +52,6 @@ const options_entry osd_options::s_option_entries[] = { OSDOPTION_NUMSCREENS "(1-4)", "1", OPTION_INTEGER, "number of screens to create; usually, you want just one" }, { OSDOPTION_WINDOW ";w", "0", OPTION_BOOLEAN, "enable window mode; otherwise, full screen mode is assumed" }, { OSDOPTION_MAXIMIZE ";max", "1", OPTION_BOOLEAN, "default to maximized windows; otherwise, windows will be minimized" }, - { OSDOPTION_KEEPASPECT ";ka", "1", OPTION_BOOLEAN, "constrain to the proper aspect ratio" }, - { OSDOPTION_UNEVENSTRETCH ";ues", "1", OPTION_BOOLEAN, "allow non-integer stretch factors" }, { OSDOPTION_WAITVSYNC ";vs", "0", OPTION_BOOLEAN, "enable waiting for the start of VBLANK before flipping screens; reduces tearing effects" }, { OSDOPTION_SYNCREFRESH ";srf", "0", OPTION_BOOLEAN, "enable using the start of VBLANK for throttling instead of the game time" }, diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h index 27e8d29d4a5..a2418cfc8b7 100644 --- a/src/osd/modules/lib/osdobj_common.h +++ b/src/osd/modules/lib/osdobj_common.h @@ -45,8 +45,6 @@ #define OSDOPTION_NUMSCREENS "numscreens" #define OSDOPTION_WINDOW "window" #define OSDOPTION_MAXIMIZE "maximize" -#define OSDOPTION_KEEPASPECT "keepaspect" -#define OSDOPTION_UNEVENSTRETCH "unevenstretch" #define OSDOPTION_WAITVSYNC "waitvsync" #define OSDOPTION_SYNCREFRESH "syncrefresh" @@ -109,8 +107,6 @@ public: int numscreens() const { return int_value(OSDOPTION_NUMSCREENS); } bool window() const { return bool_value(OSDOPTION_WINDOW); } bool maximize() const { return bool_value(OSDOPTION_MAXIMIZE); } - bool keep_aspect() const { return bool_value(OSDOPTION_KEEPASPECT); } - bool uneven_stretch() const { return bool_value(OSDOPTION_UNEVENSTRETCH); } bool wait_vsync() const { return bool_value(OSDOPTION_WAITVSYNC); } bool sync_refresh() const { return bool_value(OSDOPTION_SYNCREFRESH); } diff --git a/src/osd/modules/osdwindow.h b/src/osd/modules/osdwindow.h index 6081d47c010..b27a3b299be 100644 --- a/src/osd/modules/osdwindow.h +++ b/src/osd/modules/osdwindow.h @@ -110,8 +110,10 @@ public: const char *devicename() { return m_name[0] ? m_name : "UNKNOWN"; } - float aspect(); + float aspect() { return m_aspect; } + float pixel_aspect() { return m_aspect / ((float)m_pos_size.width() / (float)m_pos_size.height()); } + void update_resolution(const int new_width, const int new_height) { m_pos_size.resize(new_width, new_height); } void set_aspect(const float a) { m_aspect = a; } bool is_primary() { return m_is_primary; } @@ -131,6 +133,7 @@ private: void * m_handle; // handle to the monitor float m_aspect; // computed/configured aspect ratio of the physical device + float m_pixel_aspect; // computed pixel aspect ratio }; class osd_window_config @@ -166,12 +169,11 @@ public: int prescale() const { return m_prescale; }; - float aspect() const { return monitor()->aspect(); } + float pixel_aspect() const { return monitor()->pixel_aspect(); } virtual osd_dim get_size() = 0; #ifdef OSD_SDL - virtual osd_dim blit_surface_size() = 0; virtual osd_monitor_info *monitor() const = 0; virtual SDL_Window *sdl_window() = 0; #else diff --git a/src/osd/modules/render/draw13.cpp b/src/osd/modules/render/draw13.cpp index acf946b715d..f189fc48cca 100644 --- a/src/osd/modules/render/draw13.cpp +++ b/src/osd/modules/render/draw13.cpp @@ -960,12 +960,12 @@ texture_info * renderer_sdl1::texture_update(const render_primitive &prim) render_primitive_list *renderer_sdl1::get_primitives() { - osd_dim nd = window().blit_surface_size(); + osd_dim nd = window().get_size(); if (nd != m_blit_dim) { m_blit_dim = nd; notify_changed(); } - window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().aspect()); + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); return &window().target()->get_primitives(); } diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h index 806bc651344..5da751964c4 100644 --- a/src/osd/modules/render/drawbgfx.h +++ b/src/osd/modules/render/drawbgfx.h @@ -49,7 +49,7 @@ public: virtual render_primitive_list *get_primitives() override { osd_dim wdim = window().get_size(); - window().target()->set_bounds(wdim.width(), wdim.height(), window().aspect()); + window().target()->set_bounds(wdim.width(), wdim.height(), window().pixel_aspect()); return &window().target()->get_primitives(); } diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp index e927c36458f..4b8cc430640 100644 --- a/src/osd/modules/render/drawd3d.cpp +++ b/src/osd/modules/render/drawd3d.cpp @@ -204,7 +204,7 @@ render_primitive_list *renderer_d3d9::get_primitives() GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen()); if (rect_width(&client) > 0 && rect_height(&client) > 0) { - window().target()->set_bounds(rect_width(&client), rect_height(&client), window().aspect()); + window().target()->set_bounds(rect_width(&client), rect_height(&client), window().pixel_aspect()); window().target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh()); } if (m_shaders != nullptr) diff --git a/src/osd/modules/render/drawgdi.cpp b/src/osd/modules/render/drawgdi.cpp index 354d6950e30..ec1e5f57a4a 100644 --- a/src/osd/modules/render/drawgdi.cpp +++ b/src/osd/modules/render/drawgdi.cpp @@ -47,7 +47,7 @@ render_primitive_list *renderer_gdi::get_primitives() { RECT client; GetClientRect(window().m_hwnd, &client); - window().target()->set_bounds(rect_width(&client), rect_height(&client), window().aspect()); + window().target()->set_bounds(rect_width(&client), rect_height(&client), window().pixel_aspect()); return &window().target()->get_primitives(); } diff --git a/src/osd/modules/render/drawnone.cpp b/src/osd/modules/render/drawnone.cpp index 5e1b4aa05dd..d266369e7a6 100644 --- a/src/osd/modules/render/drawnone.cpp +++ b/src/osd/modules/render/drawnone.cpp @@ -23,6 +23,6 @@ render_primitive_list *renderer_none::get_primitives() { RECT client; GetClientRect(window().m_hwnd, &client); - window().target()->set_bounds(rect_width(&client), rect_height(&client), window().aspect()); + window().target()->set_bounds(rect_width(&client), rect_height(&client), window().pixel_aspect()); return &window().target()->get_primitives(); } diff --git a/src/osd/modules/render/drawogl.h b/src/osd/modules/render/drawogl.h index 3d3d3235e6e..69cd576c32d 100644 --- a/src/osd/modules/render/drawogl.h +++ b/src/osd/modules/render/drawogl.h @@ -141,17 +141,13 @@ public: #endif virtual render_primitive_list *get_primitives() override { -#ifdef OSD_WINDOWS osd_dim nd = window().get_size(); -#else - osd_dim nd = window().blit_surface_size(); -#endif if (nd != m_blit_dim) { m_blit_dim = nd; notify_changed(); } - window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().aspect()); + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); return &window().target()->get_primitives(); } diff --git a/src/osd/modules/render/drawsdl.cpp b/src/osd/modules/render/drawsdl.cpp index 005d523cf9a..932f88acc2b 100644 --- a/src/osd/modules/render/drawsdl.cpp +++ b/src/osd/modules/render/drawsdl.cpp @@ -672,12 +672,12 @@ static void yuv_RGB_to_YUY2X2(const UINT16 *bitmap, UINT8 *ptr, const int pitch, render_primitive_list *renderer_sdl2::get_primitives() { - osd_dim nd = window().blit_surface_size(); + osd_dim nd = window().get_size(); if (nd != m_blit_dim) { m_blit_dim = nd; notify_changed(); } - window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().aspect()); + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); return &window().target()->get_primitives(); } diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp index b089988c84a..43da8cc2355 100644 --- a/src/osd/sdl/video.cpp +++ b/src/osd/sdl/video.cpp @@ -124,22 +124,6 @@ void sdl_monitor_info::refresh() m_is_primary = (m_handle == 0); } -//============================================================ -// sdlvideo_monitor_get_aspect -//============================================================ - -float osd_monitor_info::aspect() -{ - // FIXME: returning 0 looks odd, video_config is bad - if (video_config.keepaspect) - { - return m_aspect / ((float)m_pos_size.width() / (float)m_pos_size.height()); - } - return 0.0f; -} - - - //============================================================ // update @@ -300,13 +284,6 @@ static void check_osd_inputs(running_machine &machine) } } - if (machine.ui_input().pressed(IPT_OSD_2)) - { - //FIXME: on a per window basis - video_config.fullstretch = !video_config.fullstretch; - machine.ui().popup_time(1, "Uneven stretch %s", video_config.fullstretch? "enabled":"disabled"); - } - if (machine.ui_input().pressed(IPT_OSD_4)) { //FIXME: on a per window basis @@ -346,7 +323,6 @@ void sdl_osd_interface::extract_video_config() video_config.filter = options().filter(); video_config.keepaspect = options().keep_aspect(); video_config.numscreens = options().numscreens(); - video_config.fullstretch = options().uneven_stretch(); #ifdef SDLMAME_X11 video_config.restrictonemonitor = !options().use_all_heads(); #endif diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp index b58167f128c..35d5bf78e57 100644 --- a/src/osd/sdl/window.cpp +++ b/src/osd/sdl/window.cpp @@ -388,94 +388,6 @@ void sdl_osd_interface::window_exit() } -//============================================================ -// sdlwindow_blit_surface_size -//============================================================ - -static inline int better_mode(int width0, int height0, int width1, int height1, float desired_aspect) -{ - float aspect0 = (float)width0 / (float)height0; - float aspect1 = (float)width1 / (float)height1; - return (fabs(desired_aspect - aspect0) < fabs(desired_aspect - aspect1)) ? 0 : 1; -} - -osd_dim sdl_window_info::blit_surface_size() -{ - osd_dim window_dim = get_size(); - - int newwidth, newheight; - int xscale = 1, yscale = 1; - float desired_aspect = 1.0f; - INT32 target_width = window_dim.width(); - INT32 target_height = window_dim.height(); - - // start with the minimum size - m_target->compute_minimum_size(newwidth, newheight); - - // compute the appropriate visible area if we're trying to keepaspect - if (video_config.keepaspect) - { - // make sure the monitor is up-to-date - m_target->compute_visible_area(target_width, target_height, m_monitor->aspect(), m_target->orientation(), target_width, target_height); - desired_aspect = (float)target_width / (float)target_height; - } - - // non-integer scaling - often gives more pleasing results in full screen - if (!video_config.fullstretch) - { - // compute maximum integral scaling to fit the window - xscale = (target_width + 2) / newwidth; - yscale = (target_height + 2) / newheight; - - // try a little harder to keep the aspect ratio if desired - if (video_config.keepaspect) - { - // if we could stretch more in the X direction, and that makes a better fit, bump the xscale - while (newwidth * (xscale + 1) <= window_dim.width() && - better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) - xscale++; - - // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale - while (newheight * (yscale + 1) <= window_dim.height() && - better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) - yscale++; - - // now that we've maxed out, see if backing off the maximally stretched one makes a better fit - if (window_dim.width() - newwidth * xscale < window_dim.height() - newheight * yscale) - { - while (better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect) && (xscale >= 0)) - xscale--; - } - else - { - while (better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect) && (yscale >= 0)) - yscale--; - } - } - - // ensure at least a scale factor of 1 - if (xscale <= 0) xscale = 1; - if (yscale <= 0) yscale = 1; - - // apply the final scale - newwidth *= xscale; - newheight *= yscale; - } - else - { - newwidth = target_width; - newheight = target_height; - } - - //FIXME: really necessary to distinguish for yuv_modes ? - if (m_target->zoom_to_screen() - && (video_config.scale_mode == VIDEO_SCALE_MODE_NONE )) - newwidth = window_dim.width(); - - return osd_dim(newwidth, newheight); -} - - //============================================================ // sdlwindow_resize // (main thread) @@ -997,27 +909,10 @@ OSDWORK_CALLBACK( sdl_window_info::complete_create_wt ) // if we have a remembered size force the new window size to it temp = window->m_windowed_dim; } + else if (window->m_startmaximized) + temp = window->get_max_bounds(video_config.keepaspect ); else - { - if (window->m_startmaximized) - { - temp = window->get_max_bounds(video_config.keepaspect ); - } - else - { -#if 0 - // Couriersud: This code never has worked with the last version of get_min_bounds - /* Create the window directly with the correct aspect - instead of letting sdlwindow_blit_surface_size() resize it - this stops the window from "flashing" from the wrong aspect - size to the right one at startup. */ - tempwidth = (window->m_win_config.width != 0) ? window->m_win_config.width : 640; - tempheight = (window->m_win_config.height != 0) ? window->m_win_config.height : 480; -#endif - temp = window->get_min_bounds(video_config.keepaspect ); - } - } - + temp = window->get_min_bounds(video_config.keepaspect ); // create the window ..... @@ -1059,9 +954,14 @@ OSDWORK_CALLBACK( sdl_window_info::complete_create_wt ) #if defined(SDLMAME_WIN32) SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); #endif + + // get monitor work area for centering + osd_rect work = window->monitor()->usuable_position_size(); + // create the SDL window window->m_sdl_window = SDL_CreateWindow(window->m_title, - window->monitor()->position_size().left(), window->monitor()->position_size().top(), + work.left() + (work.width() - temp.width()) / 2, + work.top() + (work.height() - temp.height()) / 2, temp.width(), temp.height(), window->m_extra_flags); //window().sdl_window() = SDL_CreateWindow(window().m_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, // width, height, m_extra_flags); @@ -1124,7 +1024,12 @@ OSDWORK_CALLBACK( sdl_window_info::complete_create_wt ) } } } + + // update monitor resolution after mode change to ensure proper pixel aspect window->monitor()->refresh(); + if (window->fullscreen() && video_config.switchres) + window->monitor()->update_resolution(temp.width(), temp.height()); + // initialize the drawing backend if (window->renderer().create()) return (void *) &result[1]; @@ -1272,8 +1177,12 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad float pixel_aspect; osd_monitor_info *monitor = m_monitor; + // do not constrain aspect ratio for integer scaled views + if (m_target->scale_mode() != SCALE_FRACTIONAL) + return rect; + // get the pixel aspect ratio for the target monitor - pixel_aspect = monitor->aspect(); + pixel_aspect = monitor->pixel_aspect(); // determine the proposed width/height propwidth = rect.width() - extrawidth; @@ -1393,7 +1302,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) + if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL) { // first constrain with no height limit osd_rect test1(0,0,minwidth,10000); @@ -1457,11 +1366,11 @@ osd_dim sdl_window_info::get_max_bounds(int constrain) maximum = maximum.resize(tempw, temph); // constrain to fit - if (constrain) + if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL) maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT); - else - { - maximum = maximum.resize(maximum.width() - wnd_extra_width(), maximum.height() - wnd_extra_height()); - } + + // remove extra window stuff + maximum = maximum.resize(maximum.width() - wnd_extra_width(), maximum.height() - wnd_extra_height()); + return maximum.dim(); } diff --git a/src/osd/sdl/window.h b/src/osd/sdl/window.h index 6cb2a497ebb..eeb51700630 100644 --- a/src/osd/sdl/window.h +++ b/src/osd/sdl/window.h @@ -85,7 +85,6 @@ public: render_target *target() override { return m_target; } SDL_Window *sdl_window() override { return m_sdl_window; } - osd_dim blit_surface_size() override; int prescale() const { return m_prescale; } // Pointer to next window diff --git a/src/osd/windows/video.cpp b/src/osd/windows/video.cpp index a90ed28ac21..559213657da 100644 --- a/src/osd/windows/video.cpp +++ b/src/osd/windows/video.cpp @@ -152,20 +152,6 @@ void win_monitor_info::refresh() -//============================================================ -// sdlvideo_monitor_get_aspect -//============================================================ - -float osd_monitor_info::aspect() -{ - // FIXME: returning 0 looks odd, video_config is bad - if (video_config.keepaspect) - { - return m_aspect / ((float)m_pos_size.width() / (float)m_pos_size.height()); - } - return 0.0f; -} - //============================================================ // winvideo_monitor_from_handle //============================================================ @@ -369,7 +355,6 @@ void windows_osd_interface::extract_video_config() video_config.filter = options().filter(); video_config.keepaspect = options().keep_aspect(); video_config.numscreens = options().numscreens(); - video_config.fullstretch = options().uneven_stretch(); // if we are in debug mode, never go full screen if (machine().debug_flags & DEBUG_FLAG_OSD_ENABLED) diff --git a/src/osd/windows/video.h b/src/osd/windows/video.h index e3c895c1726..9e040d90b78 100644 --- a/src/osd/windows/video.h +++ b/src/osd/windows/video.h @@ -64,8 +64,6 @@ struct osd_video_config int syncrefresh; // sync only to refresh rate int switchres; // switch resolutions - int fullstretch; // FXIME: implement in windows! - // d3d, accel, opengl int filter; // enable filtering //int filter; // enable filtering, disabled if glsl_filter>0 diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp index db8330cc858..28db75a7fe1 100644 --- a/src/osd/windows/window.cpp +++ b/src/osd/windows/window.cpp @@ -1581,6 +1581,7 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR * should be used. */ window->m_monitor->refresh(); + window->m_monitor->update_resolution(LOWORD(lparam), HIWORD(lparam)); break; // set focus: if we're not the primary window, switch back @@ -1642,13 +1643,6 @@ void win_window_info::draw_video_contents(HDC dc, int update) } -static inline int better_mode(int width0, int height0, int width1, int height1, float desired_aspect) -{ - float aspect0 = (float)width0 / (float)height0; - float aspect1 = (float)width1 / (float)height1; - return (fabs(desired_aspect - aspect0) < fabs(desired_aspect - aspect1)) ? 0 : 1; -} - //============================================================ // constrain_to_aspect_ratio // (window thread) @@ -1661,19 +1655,19 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad INT32 propwidth, propheight; INT32 minwidth, minheight; INT32 maxwidth, maxheight; + INT32 viswidth, visheight; INT32 adjwidth, adjheight; - float desired_aspect = 1.0f; - osd_dim window_dim = get_size(); - INT32 target_width = window_dim.width(); - INT32 target_height = window_dim.height(); - INT32 xscale = 1, yscale = 1; - int newwidth, newheight; + float pixel_aspect; osd_monitor_info *monitor = winwindow_video_window_monitor(&rect); assert(GetCurrentThreadId() == window_threadid); + // do not constrain aspect ratio for integer scaled views + if (m_target->scale_mode() != SCALE_FRACTIONAL) + return rect; + // get the pixel aspect ratio for the target monitor - float pixel_aspect = monitor->aspect(); + pixel_aspect = monitor->pixel_aspect(); // determine the proposed width/height propwidth = rect.width() - extrawidth; @@ -1701,58 +1695,6 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad // get the minimum width/height for the current layout m_target->compute_minimum_size(minwidth, minheight); - // compute the appropriate visible area if we're trying to keepaspect - if (video_config.keepaspect) - { - // make sure the monitor is up-to-date - m_target->compute_visible_area(target_width, target_height, m_monitor->aspect(), m_target->orientation(), target_width, target_height); - desired_aspect = (float)target_width / (float)target_height; - } - - // non-integer scaling - often gives more pleasing results in full screen - newwidth = target_width; - newheight = target_height; - if (!video_config.fullstretch) - { - // compute maximum integral scaling to fit the window - xscale = (target_width + 2) / newwidth; - yscale = (target_height + 2) / newheight; - - // try a little harder to keep the aspect ratio if desired - if (video_config.keepaspect) - { - // if we could stretch more in the X direction, and that makes a better fit, bump the xscale - while (newwidth * (xscale + 1) <= window_dim.width() && - better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) - xscale++; - - // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale - while (newheight * (yscale + 1) <= window_dim.height() && - better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) - yscale++; - - // now that we've maxed out, see if backing off the maximally stretched one makes a better fit - if (window_dim.width() - newwidth * xscale < window_dim.height() - newheight * yscale) - { - while (better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect) && (xscale >= 0)) - xscale--; - } - else - { - while (better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect) && (yscale >= 0)) - yscale--; - } - } - - // ensure at least a scale factor of 1 - if (xscale <= 0) xscale = 1; - if (yscale <= 0) yscale = 1; - - // apply the final scale - newwidth *= xscale; - newheight *= yscale; - } - // clamp against the absolute minimum propwidth = MAX(propwidth, MIN_WINDOW_DIM); propheight = MAX(propheight, MIN_WINDOW_DIM); @@ -1783,9 +1725,12 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad propwidth = MIN(propwidth, maxwidth); propheight = MIN(propheight, maxheight); + // compute the visible area based on the proposed rectangle + m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), viswidth, visheight); + // compute the adjustments we need to make - adjwidth = (propwidth + extrawidth) - rect.width(); - adjheight = (propheight + extraheight) - rect.height(); + adjwidth = (viswidth + extrawidth) - rect.width(); + adjheight = (visheight + extraheight) - rect.height(); // based on which corner we're adjusting, constrain in different ways osd_rect ret(rect); @@ -1812,7 +1757,6 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad ret = rect.move_by(0, -adjheight).resize(rect.width() + adjwidth, rect.height() + adjheight); break; } - return ret; } @@ -1843,7 +1787,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) + if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL) { // first constrain with no height limit osd_rect test1(0,0,minwidth,10000); @@ -1903,15 +1847,9 @@ osd_dim win_window_info::get_max_bounds(int constrain) maximum = maximum.resize(tempw, temph); // constrain to fit - if (constrain) - { + if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL) maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT); - } - else - { - // No - the maxima returned by usable_position_size are in window units, not usable units - //maximum = maximum.resize(maximum.width() - wnd_extra_width(), maximum.height() - wnd_extra_height()); - } + return maximum.dim(); } diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp index 3a29e5f19ec..5638628d121 100644 --- a/src/osd/windows/winmain.cpp +++ b/src/osd/windows/winmain.cpp @@ -275,10 +275,6 @@ const options_entry windows_options::s_option_entries[] = { nullptr, nullptr, OPTION_HEADER, "WINDOWS VIDEO OPTIONS" }, { WINOPTION_MENU, "0", OPTION_BOOLEAN, "enables menu bar if available by UI implementation" }, - // DirectDraw-specific options - { nullptr, nullptr, OPTION_HEADER, "DIRECTDRAW-SPECIFIC OPTIONS" }, - { WINOPTION_HWSTRETCH ";hws", "1", OPTION_BOOLEAN, "enables hardware stretching" }, - // post-processing options { nullptr, nullptr, OPTION_HEADER, "DIRECT3D POST-PROCESSING OPTIONS" }, { WINOPTION_HLSL_ENABLE";hlsl", "0", OPTION_BOOLEAN, "enables HLSL post-processing (PS3.0 required)" }, diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index 6ceecd2173a..9867cc4c08a 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -25,9 +25,6 @@ // video options #define WINOPTION_MENU "menu" -// DirectDraw-specific options -#define WINOPTION_HWSTRETCH "hwstretch" - // core post-processing options #define WINOPTION_HLSL_ENABLE "hlsl_enable" #define WINOPTION_HLSLPATH "hlslpath" @@ -128,9 +125,6 @@ public: // video options bool menu() const { return bool_value(WINOPTION_MENU); } - // DirectDraw-specific options - bool hwstretch() const { return bool_value(WINOPTION_HWSTRETCH); } - // core post-processing options const char *screen_post_fx_dir() const { return value(WINOPTION_HLSLPATH); } bool d3d_hlsl_enable() const { return bool_value(WINOPTION_HLSL_ENABLE); }