From b14605d6c97570ba71ffe5a1d51e6b46006e3941 Mon Sep 17 00:00:00 2001 From: Volker Ruppert Date: Fri, 27 Dec 2024 19:48:54 +0100 Subject: [PATCH] Voodoo: Update VGA update frequency if required after timing change. Added bool return value at Voodoo update() to indicate a timing change. VGA core then calls set_update_timer() in vsync update mode. Voodoo no longer reports mode and frequency if invalid. This should fix issue #434. --- bochs/iodev/display/banshee.cc | 5 +++-- bochs/iodev/display/vgacore.cc | 6 +++++- bochs/iodev/display/vgacore.h | 2 +- bochs/iodev/display/voodoo.cc | 19 ++++++++++++------- bochs/iodev/display/voodoo.h | 5 +++-- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/bochs/iodev/display/banshee.cc b/bochs/iodev/display/banshee.cc index 1a7c3eec5..f1a883baa 100644 --- a/bochs/iodev/display/banshee.cc +++ b/bochs/iodev/display/banshee.cc @@ -642,7 +642,7 @@ bool bx_banshee_c::chromakey_check(Bit32u color, Bit8u bpp) return pass; } -void bx_banshee_c::update(void) +bool bx_banshee_c::update(void) { Bit32u start; unsigned iHeight, iWidth, riHeight, riWidth; @@ -689,7 +689,7 @@ void bx_banshee_c::update(void) if ((start + pitch * (riHeight - 1) + riWidth) > (v->fbi.mask + 1)) { BX_ERROR(("skip address wrap during update() (start = 0x%08x)", start)); BX_UNLOCK(render_mutex); - return; + return false; } if (bx_gui->graphics_tile_info_common(&info)) { if (info.snapshot_mode) { @@ -985,6 +985,7 @@ void bx_banshee_c::update(void) } else { bx_voodoo_base_c::update(); } + return false; } Bit32u bx_banshee_c::get_retrace(bool hv) diff --git a/bochs/iodev/display/vgacore.cc b/bochs/iodev/display/vgacore.cc index 0f2cf453a..41e12f130 100644 --- a/bochs/iodev/display/vgacore.cc +++ b/bochs/iodev/display/vgacore.cc @@ -2407,7 +2407,11 @@ void bx_vgacore_c::vga_timer_handler(void *this_ptr) bx_vgacore_c *vgadev = (bx_vgacore_c *) this_ptr; #if BX_SUPPORT_PCI if (vgadev->s.vga_override && (vgadev->s.nvgadev != NULL)) { - vgadev->s.nvgadev->update(); + if (vgadev->s.nvgadev->update()) { + if (vgadev->update_mode_vsync) { + vgadev->set_update_timer(0); + } + } } else #endif diff --git a/bochs/iodev/display/vgacore.h b/bochs/iodev/display/vgacore.h index 2736a1be0..c2b733816 100644 --- a/bochs/iodev/display/vgacore.h +++ b/bochs/iodev/display/vgacore.h @@ -75,7 +75,7 @@ class bx_nonvga_device_c : public bx_pci_device_c { virtual void redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height) {} virtual void refresh_display(void *this_ptr, bool redraw) {} - virtual void update(void) {} + virtual bool update(void) {return false;} virtual Bit32u get_vtotal_usec(void) {return 0;} }; #endif diff --git a/bochs/iodev/display/voodoo.cc b/bochs/iodev/display/voodoo.cc index 59a474342..1b9fe7ed0 100644 --- a/bochs/iodev/display/voodoo.cc +++ b/bochs/iodev/display/voodoo.cc @@ -553,7 +553,7 @@ void bx_voodoo_base_c::redraw_area(unsigned x0, unsigned y0, unsigned width, } } -void bx_voodoo_base_c::update(void) +bool bx_voodoo_base_c::update(void) { Bit32u start; unsigned iHeight, iWidth, riHeight, riWidth; @@ -567,9 +567,11 @@ void bx_voodoo_base_c::update(void) bx_svga_tileinfo_t info; BX_LOCK(render_mutex); + bool retval = s.vdraw.vfreq_update; + s.vdraw.vfreq_update = false; if (!s.vdraw.gui_update_pending) { BX_UNLOCK(render_mutex); - return; + return retval; } BX_LOCK(fifo_mutex); if (s.model >= VOODOO_BANSHEE) { @@ -601,7 +603,7 @@ void bx_voodoo_base_c::update(void) if ((start + pitch * (riHeight - 1) + riWidth) > (v->fbi.mask + 1)) { BX_ERROR(("skip address wrap during update() (start = 0x%08x)", start)); BX_UNLOCK(render_mutex); - return; + return retval; } if (bx_gui->graphics_tile_info_common(&info)) { if (info.snapshot_mode) { @@ -672,6 +674,7 @@ void bx_voodoo_base_c::update(void) } s.vdraw.gui_update_pending = 0; BX_UNLOCK(render_mutex); + return retval; } void bx_voodoo_base_c::reg_write(Bit32u reg, Bit32u value) @@ -948,7 +951,7 @@ void bx_voodoo_1_2_c::mode_change_timer() bool bx_voodoo_1_2_c::update_timing(void) { int htotal, vtotal, hsync, vsync; - float hfreq; + float hfreq, old_vertfreq = v->vertfreq; if (!s.vdraw.clock_enabled || !s.vdraw.output_on) return 0; @@ -970,6 +973,7 @@ bool bx_voodoo_1_2_c::update_timing(void) hfreq /= 2; } v->vertfreq = hfreq / (float)vtotal; + s.vdraw.vfreq_update = (v->vertfreq != old_vertfreq); s.vdraw.htotal_usec = (unsigned)(1000000.0 / hfreq); s.vdraw.vtotal_usec = (unsigned)(1000000.0 / v->vertfreq); s.vdraw.htime_to_pixel = (double)htotal / (1000000.0 / hfreq); @@ -982,11 +986,12 @@ bool bx_voodoo_1_2_c::update_timing(void) bx_gui->dimension_update(v->fbi.width, v->fbi.height, 0, 0, 16); vertical_timer_handler(this); } - BX_INFO(("Voodoo output %dx%d@%uHz", v->fbi.width, v->fbi.height, (unsigned)v->vertfreq)); v->fbi.swaps_pending = 0; - v->vtimer_running = 1; - if (v->vidclk != 0.0) + if (v->vidclk != 0.0) { + BX_INFO(("Voodoo output %dx%d@%uHz", v->fbi.width, v->fbi.height, (unsigned)v->vertfreq)); bx_virt_timer.activate_timer(s.vertical_timer_id, (Bit32u)s.vdraw.vtotal_usec, 1); + v->vtimer_running = 1; + } return 1; } diff --git a/bochs/iodev/display/voodoo.h b/bochs/iodev/display/voodoo.h index f7b2ca3b3..958e5c9f4 100644 --- a/bochs/iodev/display/voodoo.h +++ b/bochs/iodev/display/voodoo.h @@ -37,6 +37,7 @@ typedef struct { Bit64u vsync_usec; double htime_to_pixel; Bit64u frame_start; + bool vfreq_update; bool clock_enabled; bool output_on; bool override_on; @@ -66,7 +67,7 @@ class bx_voodoo_base_c : public bx_nonvga_device_c { virtual void refresh_display(void *this_ptr, bool redraw); virtual void redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height); - virtual void update(void); + virtual bool update(void); virtual bool update_timing(void) {return 0;} virtual Bit32u get_retrace(bool hv) {return 0;} virtual Bit32u get_vtotal_usec(void) {return 0;} @@ -127,7 +128,7 @@ class bx_banshee_c : public bx_voodoo_base_c { virtual void register_state(void); virtual void after_restore_state(void); - virtual void update(void); + virtual bool update(void); virtual bool update_timing(void); virtual Bit32u get_retrace(bool hv);