WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] pvfb/ioemu: transmit refresh interval adv

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] pvfb/ioemu: transmit refresh interval advice from backend to frontend
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 12 May 2008 09:40:12 -0700
Delivery-date: Mon, 12 May 2008 09:40:26 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] pvfb/ioemu: transmit refresh interval advice from backend to frontend, Xen patchbot-unstable <=