From 56a55eb6ce792eab2c336a9b891a0ea2808dbc9e Mon Sep 17 00:00:00 2001 From: hap Date: Mon, 24 Feb 2025 18:37:08 +0100 Subject: [PATCH] screen: remember last partial updates reset time because of scheduler time travel issue --- src/emu/screen.cpp | 19 +++++++++++++++++++ src/emu/screen.h | 7 ++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp index b14e9c39d84..f2fbb290303 100644 --- a/src/emu/screen.cpp +++ b/src/emu/screen.cpp @@ -555,6 +555,7 @@ screen_device::screen_device(const machine_config &mconfig, const char *tag, dev , m_curbitmap(0) , m_curtexture(0) , m_changed(true) + , m_last_partial_reset(attotime::zero) , m_last_partial_scan(0) , m_partial_scan_hpos(0) , m_color(rgb_t(0xff, 0xff, 0xff, 0xff)) @@ -877,6 +878,7 @@ void screen_device::device_start() save_item(NAME(m_visarea.min_y)); save_item(NAME(m_visarea.max_x)); save_item(NAME(m_visarea.max_y)); + save_item(NAME(m_last_partial_reset)); save_item(NAME(m_last_partial_scan)); save_item(NAME(m_frame_period)); save_item(NAME(m_brightness)); @@ -1169,6 +1171,14 @@ bool screen_device::update_partial(int scanline) return false; } + // skip if we already rendered this frame + // this can happen if the executing cpu timeslice is in the previous frame while scanline 0 already started + if (m_last_partial_scan == 0 && m_last_partial_reset > machine().time()) + { + LOG_PARTIAL_UPDATES(("skipped because frame was already rendered\n")); + return false; + } + // set the range of scanlines to render rectangle clip(m_visarea); clip.sety((std::max)(clip.top(), m_last_partial_scan), (std::min)(clip.bottom(), scanline)); @@ -1279,6 +1289,14 @@ void screen_device::update_now() return; } + // skip if we already rendered this frame + // this can happen if the executing cpu timeslice is in the previous frame while scanline 0 already started + if (m_last_partial_scan == 0 && m_partial_scan_hpos == 0 && m_last_partial_reset > machine().time()) + { + LOG_PARTIAL_UPDATES(("skipped because frame was already rendered\n")); + return; + } + LOG_PARTIAL_UPDATES(("update_now(): Y=%d, X=%d, last partial %d, partial hpos %d (vis %d %d)\n", current_vpos, current_hpos, m_last_partial_scan, m_partial_scan_hpos, m_visarea.right(), m_visarea.bottom())); // start off by doing a partial update up to the line before us, in case that was necessary @@ -1394,6 +1412,7 @@ void screen_device::update_now() void screen_device::reset_partial_updates() { + m_last_partial_reset = machine().time(); m_last_partial_scan = 0; m_partial_scan_hpos = 0; m_partial_updates_this_frame = 0; diff --git a/src/emu/screen.h b/src/emu/screen.h index 5eb88f08f27..9100ae5bacc 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -461,7 +461,7 @@ private: screen_update_rgb32_delegate m_screen_update_rgb32; // screen update callback (32-bit RGB) devcb_write_line m_screen_vblank; // screen vblank line callback devcb_write32 m_scanline_cb; // screen scanline callback - optional_device m_palette; // our palette + optional_device m_palette; // our palette u32 m_video_attributes; // flags describing the video system optional_memory_region m_svg_region; // the region in which the svg data is in @@ -485,6 +485,7 @@ private: u8 m_curbitmap; // current bitmap index u8 m_curtexture; // current texture index bool m_changed; // has this bitmap changed? + attotime m_last_partial_reset; // last time partial updates were reset s32 m_last_partial_scan; // scanline of last partial update s32 m_partial_scan_hpos; // horizontal pixel last rendered on this partial scanline bitmap_argb32 m_screen_overlay_bitmap; // screen overlay bitmap @@ -504,7 +505,7 @@ private: emu_timer * m_scanline0_timer; // scanline 0 timer emu_timer * m_scanline_timer; // scanline timer u64 m_frame_number; // the current frame number - u32 m_partial_updates_this_frame;// partial update counter this frame + u32 m_partial_updates_this_frame; // partial update counter this frame bool m_is_primary_screen; @@ -517,7 +518,7 @@ private: vblank_state_delegate m_callback; }; - std::vector> m_callback_list; // list of VBLANK callbacks + std::vector> m_callback_list; // list of VBLANK callbacks // auto-sizing bitmaps class auto_bitmap_item