Skip to content

Commit

Permalink
VGA core: Implemented a more accurate vertical timing.
Browse files Browse the repository at this point in the history
Now using one timer with two alternating periods. A modification of the timer code
wasn't necessary. The update mode vsync is not yet affected by this change.
  • Loading branch information
vruppert committed Jan 19, 2024
1 parent 4112a10 commit 6e48bc7
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 19 deletions.
2 changes: 1 addition & 1 deletion bochs/iodev/display/banshee.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2863,7 +2863,7 @@ void bx_voodoo_vga_c::banshee_update_mode(void)
BX_INFO(("switched to %d x %d x %d @ %d Hz", v->fbi.width, v->fbi.height,
v->banshee.disp_bpp, (unsigned)v->vertfreq));
bx_gui->dimension_update(v->fbi.width, v->fbi.height, 0, 0, v->banshee.disp_bpp);
bx_virt_timer.deactivate_timer(vsync_timer_id);
bx_virt_timer.deactivate_timer(vertical_timer_id);
// compatibilty settings for VGA core
BX_VVGA_THIS s.last_xres = v->fbi.width;
BX_VVGA_THIS s.last_yres = v->fbi.height;
Expand Down
46 changes: 32 additions & 14 deletions bochs/iodev/display/vgacore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ bx_vgacore_c::bx_vgacore_c()
{
memset(&s, 0, sizeof(s));
update_timer_id = BX_NULL_TIMER_HANDLE;
vsync_timer_id = BX_NULL_TIMER_HANDLE;
vertical_timer_id = BX_NULL_TIMER_HANDLE;
}

bx_vgacore_c::~bx_vgacore_c()
Expand Down Expand Up @@ -142,7 +142,8 @@ void bx_vgacore_c::init_standard_vga(void)
BX_VGA_THIS s.vclk[0] = 25175000;
BX_VGA_THIS s.vclk[1] = 28322000;
BX_VGA_THIS s.htotal_usec = 31;
BX_VGA_THIS s.vtotal_usec = 14285;
BX_VGA_THIS s.vtotal_usec = 14268;
BX_VGA_THIS s.vrend_usec = 13155;

BX_VGA_THIS s.max_xres = 800;
BX_VGA_THIS s.max_yres = 600;
Expand Down Expand Up @@ -237,12 +238,13 @@ void bx_vgacore_c::init_systemtimer(void)
vga_update_freq->set_runtime_param(0);
}
}
if (BX_VGA_THIS vsync_timer_id == BX_NULL_TIMER_HANDLE) {
BX_VGA_THIS vsync_timer_id = bx_virt_timer.register_timer(this, vsync_timer_handler,
if (BX_VGA_THIS vertical_timer_id == BX_NULL_TIMER_HANDLE) {
BX_VGA_THIS vertical_timer_id = bx_virt_timer.register_timer(this, vertical_timer_handler,
100000, 1, 1, BX_VGA_THIS vsync_realtime, "vga vsync");
}
BX_VGA_THIS set_update_timer(update_interval);
BX_INFO(("VSYNC using %s mode", BX_VGA_THIS vsync_realtime ? "realtime":"standard"));
BX_VGA_THIS start_vertical_timer();
}

void bx_vgacore_c::vgacore_register_state(bx_list_c *parent)
Expand Down Expand Up @@ -424,9 +426,12 @@ void bx_vgacore_c::calculate_retrace_timing()
BX_VGA_THIS s.vrend_usec = (Bit32u)(f_htotal_usec * vrend);
BX_DEBUG(("hfreq = %.1f kHz / vfreq = %.1f Hz", (hfreq / 1000), vfreq));
if (BX_VGA_THIS s.vtotal_usec < 8000) {
BX_VGA_THIS s.vtotal_usec = 50000;
BX_VGA_THIS s.vtotal_usec = 14268;
}
bx_virt_timer.activate_timer(BX_VGA_THIS vsync_timer_id, BX_VGA_THIS s.vtotal_usec, 1);
if (BX_VGA_THIS s.vrend_usec < 7000) {
BX_VGA_THIS s.vrend_usec = BX_VGA_THIS s.vtotal_usec - 1113;
}
BX_VGA_THIS start_vertical_timer();
if (BX_VGA_THIS update_mode_vsync) {
BX_VGA_THIS set_update_timer(0);
}
Expand Down Expand Up @@ -1202,9 +1207,9 @@ void bx_vgacore_c::set_override(bool enabled, void *dev)
bx_gui->dimension_update(BX_VGA_THIS s.last_xres, BX_VGA_THIS s.last_yres,
BX_VGA_THIS s.last_fh, BX_VGA_THIS s.last_fw, BX_VGA_THIS s.last_bpp);
BX_VGA_THIS vga_redraw_area(0, 0, BX_VGA_THIS s.last_xres, BX_VGA_THIS s.last_yres);
bx_virt_timer.activate_timer(BX_VGA_THIS vsync_timer_id, BX_VGA_THIS s.vtotal_usec, 1);
BX_VGA_THIS start_vertical_timer();
} else {
bx_virt_timer.deactivate_timer(BX_VGA_THIS vsync_timer_id);
bx_virt_timer.deactivate_timer(BX_VGA_THIS vertical_timer_id);
}
if (BX_VGA_THIS update_mode_vsync) {
BX_VGA_THIS set_update_timer(0);
Expand Down Expand Up @@ -2326,16 +2331,21 @@ void bx_vgacore_c::vga_timer_handler(void *this_ptr)
bx_gui->flush();
}

void bx_vgacore_c::vsync_timer_handler(void *this_ptr)
void bx_vgacore_c::vertical_timer_handler(void *this_ptr)
{
((bx_vgacore_c *)this_ptr)->vsync_timer();
((bx_vgacore_c *)this_ptr)->vertical_timer();
}

void bx_vgacore_c::vsync_timer(void)
void bx_vgacore_c::vertical_timer(void)
{
BX_VGA_THIS s.CRTC.start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
BX_VGA_THIS s.display_start_usec =
bx_virt_timer.time_usec(BX_VGA_THIS vsync_realtime) - BX_VGA_THIS s.vrend_usec;
BX_VGA_THIS vtimer_toggle ^= 1;
bx_virt_timer.activate_timer(BX_VGA_THIS vertical_timer_id,
BX_VGA_THIS vtimer_interval[BX_VGA_THIS vtimer_toggle], 0);
if (BX_VGA_THIS vtimer_toggle) {
BX_VGA_THIS s.CRTC.start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
} else {
BX_VGA_THIS s.display_start_usec = bx_virt_timer.time_usec(BX_VGA_THIS vsync_realtime);
}
}

void bx_vgacore_c::set_update_timer(Bit32u usec)
Expand Down Expand Up @@ -2366,6 +2376,14 @@ void bx_vgacore_c::set_update_timer(Bit32u usec)
}
}

void bx_vgacore_c::start_vertical_timer(void)
{
BX_VGA_THIS vtimer_toggle = 0;
BX_VGA_THIS vtimer_interval[0] = BX_VGA_THIS s.vrend_usec;
BX_VGA_THIS vtimer_interval[1] = BX_VGA_THIS s.vtotal_usec - BX_VGA_THIS s.vrend_usec;
bx_virt_timer.activate_timer(BX_VGA_THIS vertical_timer_id, vtimer_interval[0], 0);
}

#undef LOG_THIS
#define LOG_THIS vgadev->

Expand Down
14 changes: 10 additions & 4 deletions bochs/iodev/display/vgacore.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,10 @@ class bx_vgacore_c : public bx_vga_stub_c {

virtual bool get_update_mode(void) {return update_mode_vsync;}
virtual void set_update_timer(Bit32u usec);
virtual void start_vertical_timer(void);
static void vga_timer_handler(void *);
static void vsync_timer_handler(void *);
virtual void vsync_timer(void);
static void vertical_timer_handler(void *);
virtual void vertical_timer(void);
static Bit64s vga_param_handler(bx_param_c *param, bool set, Bit64s val);

protected:
Expand Down Expand Up @@ -273,12 +274,17 @@ class bx_vgacore_c : public bx_vga_stub_c {
#endif
} s; // state information

// vga update timer stuff
int update_timer_id;
int vsync_timer_id;
Bit32u vga_update_interval;
bool update_mode_vsync;
bool update_realtime;
bool update_mode_vsync;
// vertical timer stuff
int vertical_timer_id;
bool vsync_realtime;
Bit8u vtimer_toggle;
Bit32u vtimer_interval[2];
// vga config
bx_param_enum_c *vga_ext;
bool pci_enabled;
};
Expand Down

0 comments on commit 6e48bc7

Please sign in to comment.