Some work on the timing code of the Bochs display adapters.
- Voodoo: Use the VGA/Cirrus timers to drive the gui screen update. The vertical retrace emulation is still driven by a separate timer. - VGA/Cirrus: Since we are using the virtual timer, we also have to read time_usec() from it. - vgacore: removed unused timer methods.
This commit is contained in:
parent
73c914a7f6
commit
8b96faf99e
@ -430,9 +430,9 @@ vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
|
||||
# VOODOO:
|
||||
# This defines the Voodoo Graphics emulation (experimental). Currently
|
||||
# supported models are 'voodoo1' and 'voodoo2'. The Voodoo2 support is not
|
||||
# yet complete. The 'realtime' option is very similar to the vga realtime
|
||||
# option. If set to 1 (default), the Voodoo timer is based on realtime,
|
||||
# otherwise it is driven by the cpu and depends on the ips setting.
|
||||
# yet complete. The 'realtime' option controls the behaviour of the timer
|
||||
# used for the vertical retrace emulation. The gui screen update timing
|
||||
# is controlled by the related 'vga' options.
|
||||
#
|
||||
# Examples:
|
||||
# voodoo: enabled=1, model=voodoo1, realtime=1
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com"
|
||||
.TH bochsrc 5 "30 Apr 2017" "bochsrc" "The Bochs Project"
|
||||
.TH bochsrc 5 "1 May 2017" "bochsrc" "The Bochs Project"
|
||||
.\"SKIP_SECTION"
|
||||
.SH NAME
|
||||
bochsrc \- Configuration file for Bochs.
|
||||
@ -483,9 +483,9 @@ Examples:
|
||||
.I "voodoo:"
|
||||
This defines the Voodoo Graphics emulation (experimental). Currently
|
||||
supported models are 'voodoo1' and 'voodoo2'. The Voodoo2 support is not
|
||||
yet complete. The 'realtime' option is very similar to the vga realtime
|
||||
option. If set to 1 (default), the Voodoo timer is based on realtime,
|
||||
otherwise it is driven by the cpu and depends on the ips setting.
|
||||
yet complete. The 'realtime' option controls the behaviour of the timer
|
||||
used for the vertical retrace emulation. The gui screen update timing
|
||||
is controlled by the related 'vga' options.
|
||||
|
||||
Example:
|
||||
voodoo: enabled=1, model=voodoo1, realtime=1
|
||||
|
@ -821,12 +821,12 @@ void bx_svga_cirrus_c::get_text_snapshot(Bit8u **text_snapshot,
|
||||
Bit64s bx_svga_cirrus_c::svga_param_handler(bx_param_c *param, int set, Bit64s val)
|
||||
{
|
||||
if (set) {
|
||||
BX_CIRRUS_THIS update_interval = (Bit32u)(1000000 / val);
|
||||
BX_INFO(("Changing timer interval to %d", BX_CIRRUS_THIS update_interval));
|
||||
Bit32u update_interval = (Bit32u)(1000000 / val);
|
||||
BX_INFO(("Changing timer interval to %d", update_interval));
|
||||
BX_CIRRUS_THIS svga_timer_handler(theSvga);
|
||||
bx_virt_timer.activate_timer(BX_CIRRUS_THIS timer_id, BX_CIRRUS_THIS update_interval, 1);
|
||||
if (BX_CIRRUS_THIS update_interval < 300000) {
|
||||
BX_CIRRUS_THIS s.blink_counter = 300000 / (unsigned)BX_CIRRUS_THIS update_interval;
|
||||
bx_virt_timer.activate_timer(BX_CIRRUS_THIS timer_id, update_interval, 1);
|
||||
if (update_interval < 300000) {
|
||||
BX_CIRRUS_THIS s.blink_counter = 300000 / (unsigned)update_interval;
|
||||
} else {
|
||||
BX_CIRRUS_THIS s.blink_counter = 1;
|
||||
}
|
||||
@ -1228,6 +1228,12 @@ void bx_svga_cirrus_c::svga_update(void)
|
||||
{
|
||||
unsigned width, height, pitch;
|
||||
|
||||
#if BX_SUPPORT_PCI
|
||||
if (BX_CIRRUS_THIS s.vga_override && (BX_CIRRUS_THIS s.nvgadev != NULL)) {
|
||||
BX_CIRRUS_THIS s.nvgadev->update();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* skip screen update when the sequencer is in reset mode or video is disabled */
|
||||
if (! BX_CIRRUS_THIS s.sequencer.reset1 ||
|
||||
! BX_CIRRUS_THIS s.sequencer.reset2 ||
|
||||
|
@ -330,12 +330,12 @@ Bit64s bx_vga_c::vga_param_handler(bx_param_c *param, int set, Bit64s val)
|
||||
{
|
||||
// handler for runtime parameter 'vga: update_freq'
|
||||
if (set) {
|
||||
BX_VGA_THIS update_interval = (Bit32u)(1000000 / val);
|
||||
BX_INFO(("Changing timer interval to %d", BX_VGA_THIS update_interval));
|
||||
Bit32u update_interval = (Bit32u)(1000000 / val);
|
||||
BX_INFO(("Changing timer interval to %d", update_interval));
|
||||
BX_VGA_THIS timer_handler(theVga);
|
||||
bx_virt_timer.activate_timer(BX_VGA_THIS timer_id, BX_VGA_THIS update_interval, 1);
|
||||
if (BX_VGA_THIS update_interval < 300000) {
|
||||
BX_VGA_THIS s.blink_counter = 300000 / (unsigned)BX_VGA_THIS update_interval;
|
||||
bx_virt_timer.activate_timer(BX_VGA_THIS timer_id, update_interval, 1);
|
||||
if (update_interval < 300000) {
|
||||
BX_VGA_THIS s.blink_counter = 300000 / (unsigned)update_interval;
|
||||
} else {
|
||||
BX_VGA_THIS s.blink_counter = 1;
|
||||
}
|
||||
@ -378,6 +378,12 @@ void bx_vga_c::update(void)
|
||||
{
|
||||
unsigned iHeight, iWidth;
|
||||
|
||||
#if BX_SUPPORT_PCI
|
||||
if (BX_VGA_THIS s.vga_override && (BX_VGA_THIS s.nvgadev != NULL)) {
|
||||
BX_VGA_THIS s.nvgadev->update();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (BX_VGA_THIS vbe.enabled) {
|
||||
/* no screen update necessary */
|
||||
if ((BX_VGA_THIS s.vga_mem_updated==0) && BX_VGA_THIS s.graphics_ctrl.graphics_alpha)
|
||||
@ -391,7 +397,7 @@ void bx_vga_c::update(void)
|
||||
|
||||
/* skip screen update if the vertical retrace is in progress
|
||||
(using 72 Hz vertical frequency) */
|
||||
if ((bx_pc_system.time_usec() % 13888) < 70)
|
||||
if ((bx_virt_timer.time_usec(BX_VGA_THIS realtime) % 13888) < 70)
|
||||
return;
|
||||
|
||||
if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) {
|
||||
|
@ -259,18 +259,18 @@ void bx_vgacore_c::init_iohandlers(bx_read_handler_t f_read, bx_write_handler_t
|
||||
|
||||
void bx_vgacore_c::init_systemtimer(bx_timer_handler_t f_timer, param_event_handler f_param)
|
||||
{
|
||||
const bx_bool realtime = SIM->get_param_bool(BXPN_VGA_REALTIME)->get();
|
||||
BX_VGA_THIS realtime = SIM->get_param_bool(BXPN_VGA_REALTIME)->get();
|
||||
bx_param_num_c *vga_update_freq = SIM->get_param_num(BXPN_VGA_UPDATE_FREQUENCY);
|
||||
BX_VGA_THIS update_interval = (Bit32u)(1000000 / vga_update_freq->get());
|
||||
BX_INFO(("interval=%u, mode=%s", BX_VGA_THIS update_interval, realtime ? "realtime":"standard"));
|
||||
Bit32u update_interval = (Bit32u)(1000000 / vga_update_freq->get());
|
||||
BX_INFO(("interval=%u, mode=%s", update_interval, BX_VGA_THIS realtime ? "realtime":"standard"));
|
||||
if (BX_VGA_THIS timer_id == BX_NULL_TIMER_HANDLE) {
|
||||
BX_VGA_THIS timer_id = bx_virt_timer.register_timer(this, f_timer,
|
||||
BX_VGA_THIS update_interval, 1, 1, realtime, "vga");
|
||||
update_interval, 1, 1, BX_VGA_THIS realtime, "vga");
|
||||
vga_update_freq->set_handler(f_param);
|
||||
}
|
||||
// VGA text mode cursor blink frequency 1.875 Hz
|
||||
if (BX_VGA_THIS update_interval < 266666) {
|
||||
BX_VGA_THIS s.blink_counter = 266666 / (unsigned)BX_VGA_THIS update_interval;
|
||||
if (update_interval < 266666) {
|
||||
BX_VGA_THIS s.blink_counter = 266666 / (unsigned)update_interval;
|
||||
} else {
|
||||
BX_VGA_THIS s.blink_counter = 1;
|
||||
}
|
||||
@ -378,11 +378,9 @@ void bx_vgacore_c::after_restore_state(void)
|
||||
BX_VGA_THIS s.last_xres = BX_VGA_THIS s.max_xres;
|
||||
BX_VGA_THIS s.last_yres = BX_VGA_THIS s.max_yres;
|
||||
BX_VGA_THIS redraw_area(0, 0, BX_VGA_THIS s.max_xres, BX_VGA_THIS s.max_yres);
|
||||
BX_VGA_THIS update();
|
||||
bx_gui->flush();
|
||||
} else {
|
||||
bx_virt_timer.deactivate_timer(BX_VGA_THIS timer_id);
|
||||
}
|
||||
BX_VGA_THIS update();
|
||||
bx_gui->flush();
|
||||
}
|
||||
|
||||
void bx_vgacore_c::determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth)
|
||||
@ -507,7 +505,7 @@ Bit32u bx_vgacore_c::read(Bit32u address, unsigned io_len)
|
||||
// horizontal or vertical retrace period is active
|
||||
|
||||
retval = 0;
|
||||
display_usec = bx_pc_system.time_usec() % BX_VGA_THIS s.vtotal_usec;
|
||||
display_usec = bx_virt_timer.time_usec(BX_VGA_THIS realtime) % BX_VGA_THIS s.vtotal_usec;
|
||||
if ((display_usec >= BX_VGA_THIS s.vrstart_usec) &&
|
||||
(display_usec <= BX_VGA_THIS s.vrend_usec)) {
|
||||
retval |= 0x08;
|
||||
@ -1302,28 +1300,13 @@ void bx_vgacore_c::set_override(bx_bool enabled, void *dev)
|
||||
#if BX_SUPPORT_PCI
|
||||
BX_VGA_THIS s.nvgadev = (bx_nonvga_device_c*)dev;
|
||||
#endif
|
||||
if (enabled) {
|
||||
bx_virt_timer.deactivate_timer(BX_VGA_THIS timer_id);
|
||||
} else {
|
||||
bx_virt_timer.activate_timer(BX_VGA_THIS timer_id, BX_VGA_THIS update_interval, 1);
|
||||
if (!enabled) {
|
||||
bx_gui->dimension_update(BX_VGA_THIS s.last_xres, BX_VGA_THIS s.last_yres,
|
||||
BX_VGA_THIS s.last_fw, BX_VGA_THIS s.last_fh, BX_VGA_THIS s.last_bpp);
|
||||
BX_VGA_THIS redraw_area(0, 0, BX_VGA_THIS s.last_xres, BX_VGA_THIS s.last_yres);
|
||||
}
|
||||
}
|
||||
|
||||
void bx_vgacore_c::timer_handler(void *this_ptr)
|
||||
{
|
||||
bx_vgacore_c *class_ptr = (bx_vgacore_c *) this_ptr;
|
||||
class_ptr->timer();
|
||||
}
|
||||
|
||||
void bx_vgacore_c::timer(void)
|
||||
{
|
||||
update();
|
||||
bx_gui->flush();
|
||||
}
|
||||
|
||||
Bit8u bx_vgacore_c::get_vga_pixel(Bit16u x, Bit16u y, Bit16u saddr, Bit16u lc, bx_bool bs, Bit8u **plane)
|
||||
{
|
||||
Bit8u attribute, bit_no, palette_reg_val, DAC_regno;
|
||||
@ -1388,7 +1371,7 @@ bx_bool bx_vgacore_c::skip_update(void)
|
||||
return 1;
|
||||
|
||||
/* skip screen update if the vertical retrace is in progress */
|
||||
display_usec = bx_pc_system.time_usec() % BX_VGA_THIS s.vtotal_usec;
|
||||
display_usec = bx_virt_timer.time_usec(BX_VGA_THIS realtime) % BX_VGA_THIS s.vtotal_usec;
|
||||
if ((display_usec > BX_VGA_THIS s.vrstart_usec) &&
|
||||
(display_usec < BX_VGA_THIS s.vrend_usec)) {
|
||||
return 1;
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
virtual void redraw_area(unsigned x0, unsigned y0,
|
||||
unsigned width, unsigned height) {}
|
||||
virtual void refresh_display(void *this_ptr, bx_bool redraw) {}
|
||||
virtual void update(void) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -79,9 +80,6 @@ public:
|
||||
unsigned *txWidth);
|
||||
virtual void init_vga_extension(void) {}
|
||||
|
||||
static void timer_handler(void *);
|
||||
void timer(void);
|
||||
|
||||
protected:
|
||||
void init_standard_vga(void);
|
||||
void init_gui(void);
|
||||
@ -239,7 +237,7 @@ protected:
|
||||
} s; // state information
|
||||
|
||||
int timer_id;
|
||||
Bit32u update_interval;
|
||||
bx_bool realtime;
|
||||
bx_bool extension_init;
|
||||
bx_bool pci_enabled;
|
||||
};
|
||||
|
@ -160,7 +160,7 @@ bx_voodoo_c::bx_voodoo_c()
|
||||
{
|
||||
put("VOODOO");
|
||||
s.mode_change_timer_id = BX_NULL_TIMER_HANDLE;
|
||||
s.update_timer_id = BX_NULL_TIMER_HANDLE;
|
||||
s.vertical_timer_id = BX_NULL_TIMER_HANDLE;
|
||||
v = NULL;
|
||||
}
|
||||
|
||||
@ -196,14 +196,15 @@ void bx_voodoo_c::init(void)
|
||||
BX_VOODOO_THIS s.mode_change_timer_id = bx_virt_timer.register_timer(this, mode_change_timer_handler,
|
||||
1000, 0, 0, 0, "voodoo_mode_change");
|
||||
}
|
||||
if (BX_VOODOO_THIS s.update_timer_id == BX_NULL_TIMER_HANDLE) {
|
||||
BX_VOODOO_THIS s.update_timer_id = bx_virt_timer.register_timer(this, update_timer_handler,
|
||||
50000, 1, 0, BX_VOODOO_THIS s.vdraw.realtime, "voodoo_update");
|
||||
if (BX_VOODOO_THIS s.vertical_timer_id == BX_NULL_TIMER_HANDLE) {
|
||||
BX_VOODOO_THIS s.vertical_timer_id = bx_virt_timer.register_timer(this, vertical_timer_handler,
|
||||
50000, 1, 0, BX_VOODOO_THIS s.vdraw.realtime, "vertical_timer");
|
||||
}
|
||||
BX_VOODOO_THIS s.vdraw.clock_enabled = 1;
|
||||
BX_VOODOO_THIS s.vdraw.output_on = 0;
|
||||
BX_VOODOO_THIS s.vdraw.override_on = 0;
|
||||
BX_VOODOO_THIS s.vdraw.screen_update_pending = 0;
|
||||
BX_VOODOO_THIS s.vdraw.gui_update_pending = 0;
|
||||
|
||||
v = new voodoo_state;
|
||||
BX_VOODOO_THIS s.model = (Bit8u)SIM->get_param_enum("model", base)->get();
|
||||
@ -452,7 +453,7 @@ void bx_voodoo_c::mode_change_timer_handler(void *this_ptr)
|
||||
|
||||
if ((!BX_VOODOO_THIS s.vdraw.clock_enabled || !BX_VOODOO_THIS s.vdraw.output_on) && BX_VOODOO_THIS s.vdraw.override_on) {
|
||||
// switching off
|
||||
bx_virt_timer.deactivate_timer(BX_VOODOO_THIS s.update_timer_id);
|
||||
bx_virt_timer.deactivate_timer(BX_VOODOO_THIS s.vertical_timer_id);
|
||||
DEV_vga_set_override(0, NULL);
|
||||
BX_VOODOO_THIS s.vdraw.override_on = 0;
|
||||
BX_VOODOO_THIS s.vdraw.width = 0;
|
||||
@ -503,10 +504,10 @@ bx_bool bx_voodoo_c::update_timing(void)
|
||||
BX_VOODOO_THIS s.vdraw.width = v->fbi.width;
|
||||
BX_VOODOO_THIS s.vdraw.height = v->fbi.height;
|
||||
bx_gui->dimension_update(v->fbi.width, v->fbi.height, 0, 0, 16);
|
||||
update_timer_handler(NULL);
|
||||
vertical_timer_handler(NULL);
|
||||
}
|
||||
BX_INFO(("Voodoo output %dx%d@%uHz", v->fbi.width, v->fbi.height, (unsigned)vfreq));
|
||||
bx_virt_timer.activate_timer(BX_VOODOO_THIS s.update_timer_id, (Bit32u)BX_VOODOO_THIS s.vdraw.vtotal_usec, 1);
|
||||
bx_virt_timer.activate_timer(BX_VOODOO_THIS s.vertical_timer_id, (Bit32u)BX_VOODOO_THIS s.vdraw.vtotal_usec, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -515,15 +516,26 @@ void bx_voodoo_c::refresh_display(void *this_ptr, bx_bool redraw)
|
||||
if (redraw) {
|
||||
redraw_area(0, 0, v->fbi.width, v->fbi.height);
|
||||
}
|
||||
update_timer_handler(this_ptr);
|
||||
vertical_timer_handler(this_ptr);
|
||||
}
|
||||
|
||||
void bx_voodoo_c::update_timer_handler(void *this_ptr)
|
||||
void bx_voodoo_c::vertical_timer_handler(void *this_ptr)
|
||||
{
|
||||
UNUSED(this_ptr);
|
||||
|
||||
update();
|
||||
bx_gui->flush();
|
||||
BX_VOODOO_THIS s.vdraw.frame_start = bx_virt_timer.time_usec(BX_VOODOO_THIS s.vdraw.realtime);
|
||||
|
||||
if (v->fbi.vblank_swap_pending) {
|
||||
swap_buffers(v);
|
||||
}
|
||||
|
||||
rectangle re;
|
||||
re.min_x = re.min_y = 0;
|
||||
re.max_x = v->fbi.width;
|
||||
re.max_y = v->fbi.height;
|
||||
if (!voodoo_update(&re))
|
||||
return;
|
||||
BX_VOODOO_THIS s.vdraw.gui_update_pending = 1;
|
||||
}
|
||||
|
||||
void bx_voodoo_c::update(void)
|
||||
@ -537,17 +549,7 @@ void bx_voodoo_c::update(void)
|
||||
Bit8u * tile_ptr, * tile_ptr2;
|
||||
bx_svga_tileinfo_t info;
|
||||
|
||||
BX_VOODOO_THIS s.vdraw.frame_start = bx_virt_timer.time_usec(BX_VOODOO_THIS s.vdraw.realtime);
|
||||
|
||||
if (v->fbi.vblank_swap_pending) {
|
||||
swap_buffers(v);
|
||||
}
|
||||
|
||||
rectangle re;
|
||||
re.min_x = re.min_y = 0;
|
||||
re.max_x = v->fbi.width;
|
||||
re.max_y = v->fbi.height;
|
||||
if (!voodoo_update(&re))
|
||||
if (!BX_VOODOO_THIS s.vdraw.gui_update_pending)
|
||||
return;
|
||||
|
||||
Bit8u *disp_ptr = (Bit8u*)(v->fbi.ram + v->fbi.rgboffs[v->fbi.frontbuf]);
|
||||
@ -601,6 +603,7 @@ void bx_voodoo_c::update(void)
|
||||
} else {
|
||||
BX_PANIC(("cannot get svga tile info"));
|
||||
}
|
||||
BX_VOODOO_THIS s.vdraw.gui_update_pending = 0;
|
||||
}
|
||||
|
||||
void bx_voodoo_c::redraw_area(unsigned x0, unsigned y0, unsigned width,
|
||||
|
@ -39,10 +39,11 @@ typedef struct {
|
||||
bx_bool output_on;
|
||||
bx_bool override_on;
|
||||
bx_bool screen_update_pending;
|
||||
bx_bool gui_update_pending;
|
||||
bx_bool realtime;
|
||||
} vdraw;
|
||||
int mode_change_timer_id;
|
||||
int update_timer_id;
|
||||
int vertical_timer_id;
|
||||
Bit8u devfunc;
|
||||
} bx_voodoo_t;
|
||||
|
||||
@ -59,6 +60,7 @@ public:
|
||||
virtual void refresh_display(void *this_ptr, bx_bool redraw);
|
||||
virtual void redraw_area(unsigned x0, unsigned y0,
|
||||
unsigned width, unsigned height);
|
||||
virtual void update(void);
|
||||
|
||||
virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len);
|
||||
|
||||
@ -76,8 +78,7 @@ private:
|
||||
static bx_bool mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param);
|
||||
|
||||
static void mode_change_timer_handler(void *);
|
||||
static void update_timer_handler(void *);
|
||||
static void update(void);
|
||||
static void vertical_timer_handler(void *);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user