[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC] PVFB: Add refresh period to XenStore parameters?
Samuel Thibault, le Thu 01 May 2008 18:55:36 +0100, a écrit : > Getting back to that old issue. > > Samuel Thibault, le Tue 04 Mar 2008 16:12:20 +0000, a écrit : > > > * If the frontend can track changes efficiently, it sends update > > > messages to the backend, which can use them to only redisplay > > > changed areas. > > > > Well, that was actually my next target :) > > (but for that we badly need the resize/redepth support). > > > > However, that doesn't solve something that still bugs me, which is > > that the VGA emulation layer wakes up every 30ms to just notice that > > the width/height/depth registers didn't change etc. even if the actual > > window is not shown. > > What could be done is to make the backend set request-update to 0 when > the window is minimized, which makes the frontend understand that there > is temporarily no need to send updates any more, and set it back to 1 > when the window is restored. Would that be OK? Here is how it would be implemented: ioemu: transmit idleness information to avoid useless polls Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx> diff -r 32342f2b5742 extras/mini-os/fbfront.c --- a/extras/mini-os/fbfront.c Fri May 02 15:12:43 2008 +0100 +++ b/extras/mini-os/fbfront.c Fri May 02 17:05:17 2008 +0100 @@ -243,6 +243,8 @@ struct fbfront_dev { char *backend; int request_update; + struct xenbus_event *volatile events; + int width; int height; int depth; @@ -377,6 +379,8 @@ done: xenbus_unwatch_path(XBT_NIL, path); snprintf(path, sizeof(path), "%s/request-update", dev->backend); + dev->events = NULL; + xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); dev->request_update = xenbus_read_integer(path); err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */ @@ -407,12 +411,20 @@ static void fbfront_out_event(struct fbf notify_remote_via_evtchn(dev->evtchn); } +int fbfront_update_requested(struct fbfront_dev *dev) +{ + struct xenbus_event *event; + while ((event = dev->events)) { + dev->events = event->next; + dev->request_update = xenbus_read_integer(event->path); + xfree(event); + } + return dev->request_update; +} + void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height) { struct xenfb_update update; - - if (dev->request_update <= 0) - return; if (x < 0) { width += x; @@ -461,6 +473,7 @@ void shutdown_fbfront(struct fbfront_dev printk("close fb: backend at %s\n",dev->backend); + xenbus_unwatch_path_token(XBT_NIL, path, path); snprintf(path, sizeof(path), "%s/state", dev->backend); err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */ xenbus_wait_for_value(path,"5"); diff -r 32342f2b5742 extras/mini-os/include/fbfront.h --- a/extras/mini-os/include/fbfront.h Fri May 02 15:12:43 2008 +0100 +++ b/extras/mini-os/include/fbfront.h Fri May 02 17:05:17 2008 +0100 @@ -36,6 +36,7 @@ int fbfront_open(struct fbfront_dev *dev int fbfront_open(struct fbfront_dev *dev); #endif +int fbfront_update_requested(struct fbfront_dev *dev); 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 32342f2b5742 tools/ioemu/hw/xenfb.c --- a/tools/ioemu/hw/xenfb.c Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/hw/xenfb.c Fri May 02 17:05:17 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 requested_update; /* Did we request update */ char protocol[64]; /* frontend protocol */ }; @@ -706,7 +707,8 @@ static int xenfb_read_frontend_fb_config if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.otherend, "protocol", "%63s", xenfb->protocol) < 0) xenfb->protocol[0] = '\0'; - xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1"); + xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", xenfb->ds->idle ? "0" : "1"); + xenfb->requested_update = !xenfb->ds->idle; /* TODO check for permitted ranges */ fb_page = xenfb->fb.page; @@ -1189,6 +1191,17 @@ static void xenfb_update(void *opaque) static void xenfb_update(void *opaque) { struct xenfb *xenfb = opaque; + if (xenfb->ds->idle) { + if (xenfb->requested_update) { + xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "0"); + xenfb->requested_update = 0; + } + } else { + if (!xenfb->requested_update) { + xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1"); + xenfb->requested_update = 1; + } + } } /* QEMU display state changed, so refresh the framebuffer copy */ @@ -1318,7 +1331,22 @@ static void xenfb_pv_setdata(DisplayStat static void xenfb_pv_refresh(DisplayState *ds) { + struct fbfront_dev *fb_dev = ds->opaque; + vga_hw_update(); + + if (!fb_dev) + return; + + if (fbfront_update_requested(fb_dev)) { + /* Back to default interval */ + ds->gui_timer_interval = 0; + ds->idle = 0; + } else { + /* Sleeping interval */ + ds->gui_timer_interval = 500; + ds->idle = 1; + } } static void xenfb_kbd_handler(void *opaque) @@ -1447,6 +1475,7 @@ int xenfb_pv_display_init(DisplayState * ds->dpy_colourdepth = xenfb_pv_colourdepth; ds->dpy_setdata = xenfb_pv_setdata; ds->dpy_refresh = xenfb_pv_refresh; + ds->opaque = NULL; return 0; } diff -r 32342f2b5742 tools/ioemu/sdl.c --- a/tools/ioemu/sdl.c Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/sdl.c Fri May 02 17:05:17 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 32342f2b5742 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/vl.c Fri May 02 17:05:17 2008 +0100 @@ -4467,6 +4467,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 32342f2b5742 tools/ioemu/vl.h --- a/tools/ioemu/vl.h Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/vl.h Fri May 02 17:05:17 2008 +0100 @@ -939,6 +939,7 @@ struct DisplayState { void *opaque; uint32_t *palette; uint64_t gui_timer_interval; + int idle; int shared_buf; diff -r 32342f2b5742 tools/ioemu/vnc.c --- a/tools/ioemu/vnc.c Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/vnc.c Fri May 02 17:05:17 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; _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |