[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] pvfb/ioemu: transmit refresh interval advice from backend to frontend
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1210583403 -3600 # Node ID 3b20e543b52d40f76525a7e918fa347af2de00fe # Parent e3be00bd6aa963aca563692c271af762f9380ba0 pvfb/ioemu: transmit refresh interval advice from backend to frontend which permits the frontend to avoid useless polls. Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx> --- extras/mini-os/fbfront.c | 55 ++++++++++++ extras/mini-os/include/fbfront.h | 3 extras/mini-os/include/lib.h | 4 extras/mini-os/kernel.c | 67 +++++++++------ extras/mini-os/lib/sys.c | 20 ++++ tools/ioemu/hw/xenfb.c | 173 +++++++++++++++++++++++++++++++-------- tools/ioemu/sdl.c | 2 tools/ioemu/vl.c | 4 tools/ioemu/vl.h | 4 tools/ioemu/vnc.c | 47 ++++++---- xen/include/public/io/fbif.h | 21 ++++ 11 files changed, 320 insertions(+), 80 deletions(-) diff -r e3be00bd6aa9 -r 3b20e543b52d extras/mini-os/fbfront.c --- a/extras/mini-os/fbfront.c Mon May 12 10:09:12 2008 +0100 +++ b/extras/mini-os/fbfront.c Mon May 12 10:10:03 2008 +0100 @@ -255,11 +255,55 @@ struct fbfront_dev { int offset; xenbus_event_queue events; + +#ifdef HAVE_LIBC + int fd; +#endif }; void fbfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) { +#ifdef HAVE_LIBC + struct fbfront_dev *dev = data; + int fd = dev->fd; + + files[fd].read = 1; +#endif wake_up(&fbfront_queue); +} + +int fbfront_receive(struct fbfront_dev *dev, union xenfb_in_event *buf, int n) +{ + struct xenfb_page *page = dev->page; + uint32_t prod, cons; + int i; + +#ifdef HAVE_LIBC + files[dev->fd].read = 0; + mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */ +#endif + + prod = page->in_prod; + + if (prod == page->in_cons) + return 0; + + rmb(); /* ensure we see ring contents up to prod */ + + for (i = 0, cons = page->in_cons; i < n && cons != prod; i++, cons++) + memcpy(buf + i, &XENFB_IN_RING_REF(page, cons), sizeof(*buf)); + + mb(); /* ensure we got ring contents */ + page->in_cons = cons; + notify_remote_via_evtchn(dev->evtchn); + +#ifdef HAVE_LIBC + if (cons != prod) + /* still some events to read */ + files[dev->fd].read = 1; +#endif + + return i; } struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n) @@ -482,3 +526,14 @@ void shutdown_fbfront(struct fbfront_dev free(dev->backend); free(dev); } + +#ifdef HAVE_LIBC +int fbfront_open(struct fbfront_dev *dev) +{ + dev->fd = alloc_fd(FTYPE_FB); + printk("fb_open(%s) -> %d\n", dev->nodename, dev->fd); + files[dev->fd].fb.dev = dev; + return dev->fd; +} +#endif + diff -r e3be00bd6aa9 -r 3b20e543b52d extras/mini-os/include/fbfront.h --- a/extras/mini-os/include/fbfront.h Mon May 12 10:09:12 2008 +0100 +++ b/extras/mini-os/include/fbfront.h Mon May 12 10:10:03 2008 +0100 @@ -1,4 +1,5 @@ #include <xen/io/kbdif.h> +#include <xen/io/fbif.h> #include <wait.h> /* from <linux/input.h> */ @@ -36,6 +37,8 @@ int fbfront_open(struct fbfront_dev *dev int fbfront_open(struct fbfront_dev *dev); #endif +int fbfront_receive(struct fbfront_dev *dev, union xenfb_in_event *buf, int n); +extern struct wait_queue_head fbfront_queue; void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height); void fbfront_resize(struct fbfront_dev *dev, int width, int height, int stride, int depth, int offset); diff -r e3be00bd6aa9 -r 3b20e543b52d extras/mini-os/include/lib.h --- a/extras/mini-os/include/lib.h Mon May 12 10:09:12 2008 +0100 +++ b/extras/mini-os/include/lib.h Mon May 12 10:10:03 2008 +0100 @@ -141,6 +141,7 @@ enum fd_type { FTYPE_TAP, FTYPE_BLK, FTYPE_KBD, + FTYPE_FB, }; #define MAX_EVTCHN_PORTS 16 @@ -175,6 +176,9 @@ extern struct file { struct { struct kbdfront_dev *dev; } kbd; + struct { + struct fbfront_dev *dev; + } fb; struct { /* To each xenbus FD is associated a queue of watch events for this * FD. */ diff -r e3be00bd6aa9 -r 3b20e543b52d extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Mon May 12 10:09:12 2008 +0100 +++ b/extras/mini-os/kernel.c Mon May 12 10:10:03 2008 +0100 @@ -260,6 +260,7 @@ static void blkfront_thread(void *p) #define DEPTH 32 static uint32_t *fb; +static int refresh_period = 50; static struct fbfront_dev *fb_dev; static struct semaphore fbfront_sem = __SEMAPHORE_INITIALIZER(fbfront_sem, 0); @@ -333,6 +334,10 @@ static void refresh_cursor(int new_x, in static void refresh_cursor(int new_x, int new_y) { static int old_x = -1, old_y = -1; + + if (!refresh_period) + return; + if (old_x != -1 && old_y != -1) { fbfront_drawvert(old_x, old_y + 1, old_y + 8, 0xffffffff); fbfront_drawhoriz(old_x + 1, old_x + 8, old_y, 0xffffffff); @@ -358,43 +363,46 @@ static void kbdfront_thread(void *p) down(&fbfront_sem); refresh_cursor(x, y); while (1) { - union xenkbd_in_event event; + union xenkbd_in_event kbdevent; + union xenfb_in_event fbevent; + int sleep = 1; add_waiter(w, kbdfront_queue); - - if (kbdfront_receive(kbd_dev, &event, 1) == 0) - schedule(); - else switch(event.type) { + add_waiter(w, fbfront_queue); + + while (kbdfront_receive(kbd_dev, &kbdevent, 1) != 0) { + sleep = 0; + switch(kbdevent.type) { case XENKBD_TYPE_MOTION: printk("motion x:%d y:%d z:%d\n", - event.motion.rel_x, - event.motion.rel_y, - event.motion.rel_z); - x += event.motion.rel_x; - y += event.motion.rel_y; - z += event.motion.rel_z; + kbdevent.motion.rel_x, + kbdevent.motion.rel_y, + kbdevent.motion.rel_z); + x += kbdevent.motion.rel_x; + y += kbdevent.motion.rel_y; + z += kbdevent.motion.rel_z; clip_cursor(&x, &y); refresh_cursor(x, y); break; case XENKBD_TYPE_POS: printk("pos x:%d y:%d dz:%d\n", - event.pos.abs_x, - event.pos.abs_y, - event.pos.rel_z); - x = event.pos.abs_x; - y = event.pos.abs_y; - z = event.pos.rel_z; + kbdevent.pos.abs_x, + kbdevent.pos.abs_y, + kbdevent.pos.rel_z); + x = kbdevent.pos.abs_x; + y = kbdevent.pos.abs_y; + z = kbdevent.pos.rel_z; clip_cursor(&x, &y); refresh_cursor(x, y); break; case XENKBD_TYPE_KEY: printk("key %d %s\n", - event.key.keycode, - event.key.pressed ? "pressed" : "released"); - if (event.key.keycode == BTN_LEFT) { + kbdevent.key.keycode, + kbdevent.key.pressed ? "pressed" : "released"); + if (kbdevent.key.keycode == BTN_LEFT) { printk("mouse %s at (%d,%d,%d)\n", - event.key.pressed ? "clic" : "release", x, y, z); - if (event.key.pressed) { + kbdevent.key.pressed ? "clic" : "release", x, y, z); + if (kbdevent.key.pressed) { uint32_t color = rand(); fbfront_drawvert(x - 16, y - 16, y + 15, color); fbfront_drawhoriz(x - 16, x + 15, y + 16, color); @@ -402,13 +410,26 @@ static void kbdfront_thread(void *p) fbfront_drawhoriz(x - 15, x + 16, y - 16, color); fbfront_update(fb_dev, x - 16, y - 16, 33, 33); } - } else if (event.key.keycode == KEY_Q) { + } else if (kbdevent.key.keycode == KEY_Q) { struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_poweroff }; HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); do_exit(); } break; + } } + while (fbfront_receive(fb_dev, &fbevent, 1) != 0) { + sleep = 0; + switch(fbevent.type) { + case XENFB_TYPE_REFRESH_PERIOD: + refresh_period = fbevent.refresh_period.period; + printk("refresh period %d\n", refresh_period); + refresh_cursor(x, y); + break; + } + } + if (sleep) + schedule(); } } diff -r e3be00bd6aa9 -r 3b20e543b52d extras/mini-os/lib/sys.c --- a/extras/mini-os/lib/sys.c Mon May 12 10:09:12 2008 +0100 +++ b/extras/mini-os/lib/sys.c Mon May 12 10:10:03 2008 +0100 @@ -249,6 +249,16 @@ int read(int fd, void *buf, size_t nbyte } return ret * sizeof(union xenkbd_in_event); } + case FTYPE_FB: { + int ret, n; + n = nbytes / sizeof(union xenfb_in_event); + ret = fbfront_receive(files[fd].fb.dev, buf, n); + if (ret <= 0) { + errno = EAGAIN; + return -1; + } + return ret * sizeof(union xenfb_in_event); + } case FTYPE_NONE: case FTYPE_XENBUS: case FTYPE_EVTCHN: @@ -290,6 +300,7 @@ int write(int fd, const void *buf, size_ case FTYPE_EVTCHN: case FTYPE_BLK: case FTYPE_KBD: + case FTYPE_FB: break; } printk("write(%d): Bad descriptor\n", fd); @@ -348,6 +359,7 @@ int fsync(int fd) { case FTYPE_TAP: case FTYPE_BLK: case FTYPE_KBD: + case FTYPE_FB: break; } printk("fsync(%d): Bad descriptor\n", fd); @@ -394,6 +406,10 @@ int close(int fd) shutdown_kbdfront(files[fd].kbd.dev); files[fd].type = FTYPE_NONE; return 0; + case FTYPE_FB: + shutdown_fbfront(files[fd].fb.dev); + files[fd].type = FTYPE_NONE; + return 0; case FTYPE_NONE: break; } @@ -485,6 +501,7 @@ int fstat(int fd, struct stat *buf) case FTYPE_TAP: case FTYPE_BLK: case FTYPE_KBD: + case FTYPE_FB: break; } @@ -513,6 +530,7 @@ int ftruncate(int fd, off_t length) case FTYPE_TAP: case FTYPE_BLK: case FTYPE_KBD: + case FTYPE_FB: break; } @@ -624,6 +642,7 @@ static const char file_types[] = { [FTYPE_TAP] = 'T', [FTYPE_BLK] = 'B', [FTYPE_KBD] = 'K', + [FTYPE_FB] = 'G', }; #ifdef LIBC_DEBUG static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) @@ -732,6 +751,7 @@ static int select_poll(int nfds, fd_set case FTYPE_TAP: case FTYPE_BLK: case FTYPE_KBD: + case FTYPE_FB: if (FD_ISSET(i, readfds)) { if (files[i].read) n++; diff -r e3be00bd6aa9 -r 3b20e543b52d tools/ioemu/hw/xenfb.c --- a/tools/ioemu/hw/xenfb.c Mon May 12 10:09:12 2008 +0100 +++ b/tools/ioemu/hw/xenfb.c Mon May 12 10:10:03 2008 +0100 @@ -59,6 +59,7 @@ struct xenfb { int offset; /* offset of the framebuffer */ int abs_pointer_wanted; /* Whether guest supports absolute pointer */ int button_state; /* Last seen pointer button state */ + int refresh_period; /* The refresh period we have advised */ char protocol[64]; /* frontend protocol */ }; @@ -536,6 +537,41 @@ static void xenfb_on_fb_event(struct xen xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); } +static int xenfb_queue_full(struct xenfb *xenfb) +{ + struct xenfb_page *page = xenfb->fb.page; + uint32_t cons, prod; + + prod = page->in_prod; + cons = page->in_cons; + return prod - cons == XENFB_IN_RING_LEN; +} + +static void xenfb_send_event(struct xenfb *xenfb, union xenfb_in_event *event) +{ + uint32_t prod; + struct xenfb_page *page = xenfb->fb.page; + + prod = page->in_prod; + /* caller ensures !xenfb_queue_full() */ + xen_mb(); /* ensure ring space available */ + XENFB_IN_RING_REF(page, prod) = *event; + xen_wmb(); /* ensure ring contents visible */ + page->in_prod = prod + 1; + + xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); +} + +static void xenfb_send_refresh_period(struct xenfb *xenfb, int period) +{ + union xenfb_in_event event; + + memset(&event, 0, sizeof(event)); + event.type = XENFB_TYPE_REFRESH_PERIOD; + event.refresh_period.period = period; + xenfb_send_event(xenfb, &event); +} + static void xenfb_on_kbd_event(struct xenfb *xenfb) { struct xenkbd_page *page = xenfb->kbd.page; @@ -707,6 +743,7 @@ static int xenfb_read_frontend_fb_config xenfb->protocol) < 0) xenfb->protocol[0] = '\0'; xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1"); + xenfb->refresh_period = -1; /* TODO check for permitted ranges */ fb_page = xenfb->fb.page; @@ -1185,10 +1222,28 @@ static void xenfb_guest_copy(struct xenf dpy_update(xenfb->ds, x, y, w, h); } -/* Periodic update of display, no need for any in our case */ +/* Periodic update of display, transmit the refresh interval to the frontend */ static void xenfb_update(void *opaque) { struct xenfb *xenfb = opaque; + int period; + + if (xenfb_queue_full(xenfb)) + return; + + if (xenfb->ds->idle) + period = XENFB_NO_REFRESH; + else { + period = xenfb->ds->gui_timer_interval; + if (!period) + period = GUI_REFRESH_INTERVAL; + } + + /* Will have to be disabled for frontends without feature-update */ + if (xenfb->refresh_period != period) { + xenfb_send_refresh_period(xenfb, period); + xenfb->refresh_period = period; + } } /* QEMU display state changed, so refresh the framebuffer copy */ @@ -1232,11 +1287,17 @@ static int xenfb_register_console(struct } #ifdef CONFIG_STUBDOM -static struct semaphore kbd_sem = __SEMAPHORE_INITIALIZER(kbd_sem, 0); -static struct kbdfront_dev *kbd_dev; +typedef struct XenFBState { + struct semaphore kbd_sem; + struct kbdfront_dev *kbd_dev; + struct fbfront_dev *fb_dev; + void *vga_vram, *nonshared_vram; + DisplayState *ds; +} XenFBState; + +XenFBState *xs; + static char *kbd_path, *fb_path; -static void *vga_vram, *nonshared_vram; -static DisplayState *xenfb_ds; static unsigned char linux2scancode[KEY_MAX + 1]; @@ -1254,7 +1315,8 @@ int xenfb_connect_vfb(const char *path) static void xenfb_pv_update(DisplayState *ds, int x, int y, int w, int h) { - struct fbfront_dev *fb_dev = ds->opaque; + XenFBState *xs = ds->opaque; + struct fbfront_dev *fb_dev = xs->fb_dev; if (!fb_dev) return; fbfront_update(fb_dev, x, y, w, h); @@ -1262,7 +1324,8 @@ static void xenfb_pv_update(DisplayState static void xenfb_pv_resize(DisplayState *ds, int w, int h, int linesize) { - struct fbfront_dev *fb_dev = ds->opaque; + XenFBState *xs = ds->opaque; + struct fbfront_dev *fb_dev = xs->fb_dev; fprintf(stderr,"resize to %dx%d, %d required\n", w, h, linesize); ds->width = w; ds->height = h; @@ -1276,14 +1339,15 @@ static void xenfb_pv_resize(DisplayState if (ds->shared_buf) { ds->data = NULL; } else { - ds->data = nonshared_vram; + ds->data = xs->nonshared_vram; fbfront_resize(fb_dev, w, h, linesize, ds->depth, VGA_RAM_SIZE); } } static void xenfb_pv_colourdepth(DisplayState *ds, int depth) { - struct fbfront_dev *fb_dev = ds->opaque; + XenFBState *xs = ds->opaque; + struct fbfront_dev *fb_dev = xs->fb_dev; static int lastdepth = -1; if (!depth) { ds->shared_buf = 0; @@ -1301,15 +1365,16 @@ static void xenfb_pv_colourdepth(Display if (ds->shared_buf) { ds->data = NULL; } else { - ds->data = nonshared_vram; + ds->data = xs->nonshared_vram; fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, VGA_RAM_SIZE); } } static void xenfb_pv_setdata(DisplayState *ds, void *pixels) { - struct fbfront_dev *fb_dev = ds->opaque; - int offset = pixels - vga_vram; + XenFBState *xs = ds->opaque; + struct fbfront_dev *fb_dev = xs->fb_dev; + int offset = pixels - xs->vga_vram; ds->data = pixels; if (!fb_dev) return; @@ -1321,16 +1386,45 @@ static void xenfb_pv_refresh(DisplayStat vga_hw_update(); } +static void xenfb_fb_handler(void *opaque) +{ +#define FB_NUM_BATCH 4 + union xenfb_in_event buf[FB_NUM_BATCH]; + int n, i; + XenFBState *xs = opaque; + DisplayState *ds = xs->ds; + + n = fbfront_receive(xs->fb_dev, buf, FB_NUM_BATCH); + for (i = 0; i < n; i++) { + switch (buf[i].type) { + case XENFB_TYPE_REFRESH_PERIOD: + if (buf[i].refresh_period.period == XENFB_NO_REFRESH) { + /* Sleeping interval */ + ds->idle = 1; + ds->gui_timer_interval = 500; + } else { + /* Set interval */ + ds->idle = 0; + ds->gui_timer_interval = buf[i].refresh_period.period; + } + default: + /* ignore unknown events */ + break; + } + } +} + static void xenfb_kbd_handler(void *opaque) { #define KBD_NUM_BATCH 64 union xenkbd_in_event buf[KBD_NUM_BATCH]; int n, i; - DisplayState *s = opaque; + XenFBState *xs = opaque; + DisplayState *s = xs->ds; static int buttons; static int x, y; - n = kbdfront_receive(kbd_dev, buf, KBD_NUM_BATCH); + n = kbdfront_receive(xs->kbd_dev, buf, KBD_NUM_BATCH); for (i = 0; i < n; i++) { switch (buf[i].type) { @@ -1412,12 +1506,13 @@ static void kbdfront_thread(void *p) static void kbdfront_thread(void *p) { int scancode, keycode; - kbd_dev = init_kbdfront(p, 1); - if (!kbd_dev) { + XenFBState *xs = p; + xs->kbd_dev = init_kbdfront(kbd_path, 1); + if (!xs->kbd_dev) { fprintf(stderr,"can't open keyboard\n"); exit(1); } - up(&kbd_sem); + up(&xs->kbd_sem); for (scancode = 0; scancode < 128; scancode++) { keycode = atkbd_set2_keycode[atkbd_unxlate_table[scancode]]; linux2scancode[keycode] = scancode; @@ -1431,12 +1526,18 @@ int xenfb_pv_display_init(DisplayState * if (!fb_path || !kbd_path) return -1; - create_thread("kbdfront", kbdfront_thread, (void*) kbd_path); - - xenfb_ds = ds; - - ds->data = nonshared_vram = qemu_memalign(PAGE_SIZE, VGA_RAM_SIZE); + xs = qemu_mallocz(sizeof(XenFBState)); + if (!xs) + return -1; + + init_SEMAPHORE(&xs->kbd_sem, 0); + xs->ds = ds; + + create_thread("kbdfront", kbdfront_thread, (void*) xs); + + ds->data = xs->nonshared_vram = qemu_memalign(PAGE_SIZE, VGA_RAM_SIZE); memset(ds->data, 0, VGA_RAM_SIZE); + ds->opaque = xs; ds->depth = 32; ds->bgr = 0; ds->width = 640; @@ -1452,9 +1553,9 @@ int xenfb_pv_display_init(DisplayState * int xenfb_pv_display_start(void *data) { - DisplayState *ds = xenfb_ds; + DisplayState *ds; struct fbfront_dev *fb_dev; - int kbd_fd; + int kbd_fd, fb_fd; int offset = 0; unsigned long *mfns; int n = VGA_RAM_SIZE / PAGE_SIZE; @@ -1463,12 +1564,13 @@ int xenfb_pv_display_start(void *data) if (!fb_path || !kbd_path) return 0; - vga_vram = data; + ds = xs->ds; + xs->vga_vram = data; mfns = malloc(2 * n * sizeof(*mfns)); for (i = 0; i < n; i++) - mfns[i] = virtual_to_mfn(vga_vram + i * PAGE_SIZE); + mfns[i] = virtual_to_mfn(xs->vga_vram + i * PAGE_SIZE); for (i = 0; i < n; i++) - mfns[n + i] = virtual_to_mfn(nonshared_vram + i * PAGE_SIZE); + mfns[n + i] = virtual_to_mfn(xs->nonshared_vram + i * PAGE_SIZE); fb_dev = init_fbfront(fb_path, mfns, ds->width, ds->height, ds->depth, ds->linesize, 2 * n); free(mfns); @@ -1479,21 +1581,24 @@ int xenfb_pv_display_start(void *data) free(fb_path); if (ds->shared_buf) { - offset = (void*) ds->data - vga_vram; + offset = (void*) ds->data - xs->vga_vram; } else { offset = VGA_RAM_SIZE; - ds->data = nonshared_vram; + ds->data = xs->nonshared_vram; } if (offset) fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, offset); - down(&kbd_sem); + down(&xs->kbd_sem); free(kbd_path); - kbd_fd = kbdfront_open(kbd_dev); - qemu_set_fd_handler(kbd_fd, xenfb_kbd_handler, NULL, ds); - - xenfb_ds->opaque = fb_dev; + kbd_fd = kbdfront_open(xs->kbd_dev); + qemu_set_fd_handler(kbd_fd, xenfb_kbd_handler, NULL, xs); + + fb_fd = fbfront_open(fb_dev); + qemu_set_fd_handler(fb_fd, xenfb_fb_handler, NULL, xs); + + xs->fb_dev = fb_dev; return 0; } #endif diff -r e3be00bd6aa9 -r 3b20e543b52d tools/ioemu/sdl.c --- a/tools/ioemu/sdl.c Mon May 12 10:09:12 2008 +0100 +++ b/tools/ioemu/sdl.c Mon May 12 10:10:03 2008 +0100 @@ -696,9 +696,11 @@ static void sdl_refresh(DisplayState *ds if (ev->active.gain) { /* Back to default interval */ ds->gui_timer_interval = 0; + ds->idle = 0; } else { /* Sleeping interval */ ds->gui_timer_interval = 500; + ds->idle = 1; } } break; diff -r e3be00bd6aa9 -r 3b20e543b52d tools/ioemu/vl.c --- a/tools/ioemu/vl.c Mon May 12 10:09:12 2008 +0100 +++ b/tools/ioemu/vl.c Mon May 12 10:10:03 2008 +0100 @@ -130,8 +130,6 @@ #else #define DEFAULT_RAM_SIZE 128 #endif -/* in ms */ -#define GUI_REFRESH_INTERVAL 30 /* Max number of USB devices that can be specified on the commandline. */ #define MAX_USB_CMDLINE 8 @@ -4467,6 +4465,8 @@ void dumb_display_init(DisplayState *ds) ds->dpy_resize = dumb_resize; ds->dpy_colourdepth = NULL; ds->dpy_refresh = dumb_refresh; + ds->gui_timer_interval = 500; + ds->idle = 1; } /***********************************************************/ diff -r e3be00bd6aa9 -r 3b20e543b52d tools/ioemu/vl.h --- a/tools/ioemu/vl.h Mon May 12 10:09:12 2008 +0100 +++ b/tools/ioemu/vl.h Mon May 12 10:10:03 2008 +0100 @@ -929,6 +929,9 @@ extern struct soundhw soundhw[]; #define VGA_RAM_SIZE (8192 * 1024) +/* in ms */ +#define GUI_REFRESH_INTERVAL 30 + struct DisplayState { uint8_t *data; int linesize; @@ -939,6 +942,7 @@ struct DisplayState { void *opaque; uint32_t *palette; uint64_t gui_timer_interval; + int idle; int shared_buf; diff -r e3be00bd6aa9 -r 3b20e543b52d tools/ioemu/vnc.c --- a/tools/ioemu/vnc.c Mon May 12 10:09:12 2008 +0100 +++ b/tools/ioemu/vnc.c Mon May 12 10:10:03 2008 +0100 @@ -778,6 +778,7 @@ static void _vnc_update_client(void *opa vs->has_update = 0; vnc_flush(vs); vs->last_update_time = now; + vs->ds->idle = 0; vs->timer_interval /= 2; if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE) @@ -790,26 +791,29 @@ static void _vnc_update_client(void *opa vs->timer_interval += VNC_REFRESH_INTERVAL_INC; if (vs->timer_interval > VNC_REFRESH_INTERVAL_MAX) { vs->timer_interval = VNC_REFRESH_INTERVAL_MAX; - if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL && - vs->update_requested) { - /* Send a null update. If the client is no longer - interested (e.g. minimised) it'll ignore this, and we - can stop scanning the buffer until it sends another - update request. */ - /* It turns out that there's a bug in realvncviewer 4.1.2 - which means that if you send a proper null update (with - no update rectangles), it gets a bit out of sync and - never sends any further requests, regardless of whether - it needs one or not. Fix this by sending a single 1x1 - update rectangle instead. */ - vnc_write_u8(vs, 0); - vnc_write_u8(vs, 0); - vnc_write_u16(vs, 1); - send_framebuffer_update(vs, 0, 0, 1, 1); - vnc_flush(vs); - vs->last_update_time = now; - vs->update_requested--; - return; + if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) { + if (!vs->update_requested) { + vs->ds->idle = 1; + } else { + /* Send a null update. If the client is no longer + interested (e.g. minimised) it'll ignore this, and we + can stop scanning the buffer until it sends another + update request. */ + /* It turns out that there's a bug in realvncviewer 4.1.2 + which means that if you send a proper null update (with + no update rectangles), it gets a bit out of sync and + never sends any further requests, regardless of whether + it needs one or not. Fix this by sending a single 1x1 + update rectangle instead. */ + vnc_write_u8(vs, 0); + vnc_write_u8(vs, 0); + vnc_write_u16(vs, 1); + send_framebuffer_update(vs, 0, 0, 1, 1); + vnc_flush(vs); + vs->last_update_time = now; + vs->update_requested--; + return; + } } } qemu_mod_timer(vs->timer, now + vs->timer_interval); @@ -970,6 +974,7 @@ static int vnc_client_io_error(VncState qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); closesocket(vs->csock); vs->csock = -1; + vs->ds->idle = 1; buffer_reset(&vs->input); buffer_reset(&vs->output); free_queue(vs); @@ -2443,6 +2448,7 @@ static void vnc_listen_read(void *opaque vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); if (vs->csock != -1) { VNC_DEBUG("New client on socket %d\n", vs->csock); + vs->ds->idle = 0; socket_set_nonblock(vs->csock); qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque); vnc_write(vs, "RFB 003.008\n", 12); @@ -2468,6 +2474,7 @@ void vnc_display_init(DisplayState *ds) exit(1); ds->opaque = vs; + ds->idle = 1; vnc_state = vs; vs->display = NULL; vs->password = NULL; diff -r e3be00bd6aa9 -r 3b20e543b52d xen/include/public/io/fbif.h --- a/xen/include/public/io/fbif.h Mon May 12 10:09:12 2008 +0100 +++ b/xen/include/public/io/fbif.h Mon May 12 10:10:03 2008 +0100 @@ -80,14 +80,33 @@ union xenfb_out_event /* * Frontends should ignore unknown in events. - * No in events currently defined. */ + +/* + * Framebuffer refresh period advice + * Backend sends it to advise the frontend their preferred period of + * refresh. Frontends that keep the framebuffer constantly up-to-date + * just ignore it. Frontends that use the advice should immediately + * refresh the framebuffer (and send an update notification event if + * those have been requested), then use the update frequency to guide + * their periodical refreshs. + */ +#define XENFB_TYPE_REFRESH_PERIOD 1 +#define XENFB_NO_REFRESH 0 + +struct xenfb_refresh_period +{ + uint8_t type; /* XENFB_TYPE_UPDATE_PERIOD */ + uint32_t period; /* period of refresh, in ms, + * XENFB_NO_REFRESH if no refresh is needed */ +}; #define XENFB_IN_EVENT_SIZE 40 union xenfb_in_event { uint8_t type; + struct xenfb_refresh_period refresh_period; char pad[XENFB_IN_EVENT_SIZE]; }; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |