[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/7] xenfb update.



Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxxxxx>
---
 hw/xen_backend.h    |    2 +-
 hw/xen_machine_pv.c |    2 +-
 hw/xenfb.c          |  195 ++++++++++++++++++++++++++++++---------------------
 3 files changed, 116 insertions(+), 83 deletions(-)

diff --git a/hw/xen_backend.h b/hw/xen_backend.h
index 9aa8d13..8c93c9f 100644
--- a/hw/xen_backend.h
+++ b/hw/xen_backend.h
@@ -89,6 +89,6 @@ extern struct XenDevOps xen_console_ops;      /* 
xen_console.c     */
 extern struct XenDevOps xen_kbdmouse_ops;     /* xen_framebuffer.c */
 extern struct XenDevOps xen_framebuffer_ops;  /* xen_framebuffer.c */
 
-void xen_set_display(int domid);
+void xen_init_display(int domid);
 
 #endif /* QEMU_HW_XEN_BACKEND_H */
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 6bfafbb..5536842 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -71,7 +71,7 @@ static void xen_init_pv(ram_addr_t ram_size, int vga_ram_size,
     xen_be_register("vfb", &xen_framebuffer_ops);
 
     /* setup framebuffer */
-    xen_set_display(xen_domid);
+    xen_init_display(xen_domid);
 }
 
 QEMUMachine xenpv_machine = {
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 4b71bf2..135764d 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -86,6 +86,8 @@ struct XenFB {
     int               feature_update;
     int               refresh_period;
     int               bug_trigger;
+    int               have_console;
+    int               do_resize;
 
     struct {
        int x,y,w,h;
@@ -129,10 +131,11 @@ static void common_unbind(struct common *c)
 
 /* -------------------------------------------------------------------- */
 
+#ifdef CONFIG_STUBDOM
 /*
- * These two tables are not needed any more here, but left in here
- * intentionally as documentation, to show how scancode2linux[] was
- * generated, and also because xenfbfront needs them.
+ * These two tables are not needed any more, but left in here
+ * intentionally as documentation, to show how scancode2linux[]
+ * was generated.
  *
  * Tables to map from scancode to Linux input layer keycode.
  * Scancodes are hardware-specific.  These maps assumes a
@@ -172,6 +175,7 @@ const unsigned char atkbd_unxlate_table[128] = {
      19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
 
 };
+#endif
 
 /*
  * for (i = 0; i < 128; i++) {
@@ -320,12 +324,14 @@ static void xenfb_mouse_event(void *opaque,
                              int dx, int dy, int dz, int button_state)
 {
     struct XenInput *xenfb = opaque;
+    int dw = ds_get_width(xenfb->c.ds);
+    int dh = ds_get_height(xenfb->c.ds);
     int i;
 
     if (xenfb->abs_pointer_wanted)
        xenfb_send_position(xenfb,
-                           dx * (ds_get_width(xenfb->c.ds) - 1) / 0x7fff,
-                           dy * (ds_get_height(xenfb->c.ds) - 1) / 0x7fff,
+                           dx * (dw - 1) / 0x7fff,
+                           dy * (dh - 1) / 0x7fff,
                            dz);
     else
        xenfb_send_motion(xenfb, dx, dy, dz);
@@ -346,6 +352,11 @@ static int input_init(struct XenDevice *xendev)
 {
     struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
 
+    if (!in->c.ds) {
+        xen_be_printf(xendev, 1, "ds not set (yet)\n");
+       return -1;
+    }
+
     xenstore_write_be_int(xendev, "feature-abs-pointer", 1);
     return 0;
 }
@@ -547,6 +558,8 @@ static int xenfb_configure_fb(struct XenFB *xenfb, size_t 
fb_len_lim,
     xenfb->width = width;
     xenfb->height = height;
     xenfb->offset = offset;
+    xenfb->up_fullscreen = 1;
+    xenfb->do_resize = 1;
     xen_be_printf(&xenfb->c.xendev, 1, "framebuffer %dx%dx%d offset %d stride 
%d\n",
                  width, height, depth, offset, row_stride);
     return 0;
@@ -559,9 +572,9 @@ static int xenfb_configure_fb(struct XenFB *xenfb, size_t 
fb_len_lim,
                               + xenfb->offset                          \
                               + (line * xenfb->row_stride)             \
                               + (x * xenfb->depth / 8));               \
-       DST_T *dst = (DST_T *)(ds_get_data(xenfb->c.ds)                         
\
-                              + (line * ds_get_linesize(xenfb->c.ds))          
\
-                              + (x * ds_get_bytes_per_pixel(xenfb->c.ds)));    
        \
+       DST_T *dst = (DST_T *)(data                                     \
+                              + (line * linesize)                      \
+                              + (x * bpp / 8));                        \
        int col;                                                        \
        const int RSS = 32 - (RSB + GSB + BSB);                         \
        const int GSS = 32 - (GSB + BSB);                               \
@@ -581,55 +594,52 @@ static int xenfb_configure_fb(struct XenFB *xenfb, size_t 
fb_len_lim,
                (((spix << GSS) & GSM & GDM) >> GDS) |                  \
                (((spix << BSS) & BSM & BDM) >> BDS);                   \
            src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8);   \
-           dst = (DST_T *) ((unsigned long) dst + 
ds_get_bytes_per_pixel(xenfb->c.ds)); \
+           dst = (DST_T *) ((unsigned long) dst + bpp / 8);            \
        }                                                               \
     }
 
 
-/* This copies data from the guest framebuffer region, into QEMU's copy
- * NB. QEMU's copy is stored in the pixel format of a) the local X
- * server (SDL case) or b) the current VNC client pixel format.
- * When shifting between colour depths we preserve the MSB.
+/*
+ * This copies data from the guest framebuffer region, into QEMU's
+ * displaysurface. qemu uses 16 or 32 bpp.  In case the pv framebuffer
+ * uses something else we must convert and copy, otherwise we can
+ * supply the buffer directly and no thing here.
  */
 static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
 {
-    int line;
+    int line, oops = 0;
+    int bpp = ds_get_bits_per_pixel(xenfb->c.ds);
+    int linesize = ds_get_linesize(xenfb->c.ds);
+    uint8_t *data = ds_get_data(xenfb->c.ds);
 
     if (!is_buffer_shared(xenfb->c.ds->surface)) {
-       if (xenfb->depth == ds_get_bits_per_pixel(xenfb->c.ds)) { /* Perfect 
match can use fast path */
-           for (line = y ; line < (y+h) ; line++) {
-               memcpy(ds_get_data(xenfb->c.ds) + (line * 
ds_get_linesize(xenfb->c.ds)) + (x * ds_get_bytes_per_pixel(xenfb->c.ds)),
-                      xenfb->pixels + xenfb->offset + (line * 
xenfb->row_stride) + (x * xenfb->depth / 8),
-                      w * xenfb->depth / 8);
-           }
-       } else { /* Mismatch requires slow pixel munging */
-           /* 8 bit == r:3 g:3 b:2 */
-           /* 16 bit == r:5 g:6 b:5 */
-           /* 24 bit == r:8 g:8 b:8 */
-           /* 32 bit == r:8 g:8 b:8 (padding:8) */
-           if (xenfb->depth == 8) {
-               if (ds_get_bits_per_pixel(xenfb->c.ds) == 16) {
-                   BLT(uint8_t, uint16_t,   3, 3, 2,   5, 6, 5);
-               } else if (ds_get_bits_per_pixel(xenfb->c.ds) == 32) {
-                   BLT(uint8_t, uint32_t,   3, 3, 2,   8, 8, 8);
-               }
-           } else if (xenfb->depth == 16) {
-               if (ds_get_bits_per_pixel(xenfb->c.ds) == 8) {
-                   BLT(uint16_t, uint8_t,   5, 6, 5,   3, 3, 2);
-               } else if (ds_get_bits_per_pixel(xenfb->c.ds) == 32) {
-                   BLT(uint16_t, uint32_t,  5, 6, 5,   8, 8, 8);
-               }
-           } else if (xenfb->depth == 24 || xenfb->depth == 32) {
-               if (ds_get_bits_per_pixel(xenfb->c.ds) == 8) {
-                   BLT(uint32_t, uint8_t,   8, 8, 8,   3, 3, 2);
-               } else if (ds_get_bits_per_pixel(xenfb->c.ds) == 16) {
-                   BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);
-               } else if (ds_get_bits_per_pixel(xenfb->c.ds) == 32) {
-                   BLT(uint32_t, uint32_t,  8, 8, 8,   8, 8, 8);
-               }
-           }
+        switch (xenfb->depth) {
+        case 8:
+            if (bpp == 16) {
+                BLT(uint8_t, uint16_t,   3, 3, 2,   5, 6, 5);
+            } else if (bpp == 32) {
+                BLT(uint8_t, uint32_t,   3, 3, 2,   8, 8, 8);
+            } else {
+                oops = 1;
+            }
+            break;
+        case 24:
+            if (bpp == 16) {
+                BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);
+            } else if (bpp == 32) {
+                BLT(uint32_t, uint32_t,  8, 8, 8,   8, 8, 8);
+            } else {
+                oops = 1;
+            }
+            break;
+        default:
+            oops = 1;
        }
     }
+    if (oops) /* should not happen */
+        xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n",
+                      __FUNCTION__, xenfb->depth, bpp);
+
     dpy_update(xenfb->c.ds, x, y, w, h);
 }
 
@@ -685,10 +695,12 @@ static void xenfb_send_refresh_period(struct XenFB 
*xenfb, int period)
 static void xenfb_update(void *opaque)
 {
     struct XenFB *xenfb = opaque;
-    int i;
     struct DisplayChangeListener *l;
+    int dw = ds_get_width(xenfb->c.ds);
+    int dh = ds_get_height(xenfb->c.ds);
+    int i;
 
-    if (!xenfb->width || !xenfb->height)
+    if (xenfb->c.xendev.be_state != XenbusStateConnected)
         return;
 
     if (xenfb->feature_update) {
@@ -712,11 +724,12 @@ static void xenfb_update(void *opaque)
             }
         }
         if (idle)
-            period = XENFB_NO_REFRESH;
+           period = XENFB_NO_REFRESH;
 
        if (xenfb->refresh_period != period) {
            xenfb_send_refresh_period(xenfb, period);
            xenfb->refresh_period = period;
+            xen_be_printf(&xenfb->c.xendev, 1, "refresh period: %d\n", period);
        }
 #else
        ; /* nothing */
@@ -728,11 +741,8 @@ static void xenfb_update(void *opaque)
     }
 
     /* resize if needed */
-    if (xenfb->width != ds_get_width(xenfb->c.ds) ||
-        xenfb->height != ds_get_height(xenfb->c.ds) ||
-        xenfb->depth != ds_get_bits_per_pixel(xenfb->c.ds) ||
-        xenfb->row_stride != ds_get_linesize(xenfb->c.ds) ||
-        xenfb->pixels + xenfb->offset != ds_get_data(xenfb->c.ds)) {
+    if (xenfb->do_resize) {
+        xenfb->do_resize = 0;
         switch (xenfb->depth) {
         case 16:
         case 32:
@@ -747,9 +757,10 @@ static void xenfb_update(void *opaque)
             qemu_resize_displaysurface(xenfb->c.ds, xenfb->width, 
xenfb->height);
             break;
         }
+        xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d 
bpp%s\n",
+                      xenfb->width, xenfb->height, xenfb->depth,
+                      is_buffer_shared(xenfb->c.ds->surface) ? " (shared)" : 
"");
         dpy_resize(xenfb->c.ds);
-        xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d\n",
-                      xenfb->width, xenfb->height);
         xenfb->up_fullscreen = 1;
     }
 
@@ -881,6 +892,17 @@ static int fb_connect(struct XenDevice *xendev)
     if (0 != rc)
        return rc;
 
+#if 0  /* handled in xen_init_display() for now */
+    if (!fb->have_console) {
+        fb->c.ds = graphic_console_init(xenfb_update,
+                                        xenfb_invalidate,
+                                        NULL,
+                                        NULL,
+                                        fb);
+        fb->have_console = 1;
+    }
+#endif
+
     if (-1 == xenstore_read_fe_int(xendev, "feature-update", 
&fb->feature_update))
        fb->feature_update = 0;
     if (fb->feature_update)
@@ -888,7 +910,6 @@ static int fb_connect(struct XenDevice *xendev)
 
     xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n",
                  fb->feature_update, videoram);
-
     return 0;
 }
 
@@ -954,31 +975,43 @@ struct XenDevOps xen_framebuffer_ops = {
     .frontend_changed = fb_frontend_changed,
 };
 
-static void xen_set_display_type(int domid, const char *type, DisplayState *ds)
+/*
+ * FIXME/TODO: Kill this.
+ * Temporary needed while DisplayState reorganization is in flight.
+ */
+void xen_init_display(int domid)
 {
-    struct XenDevice *xendev;
-    struct common *c;
+    struct XenDevice *xfb, *xin;
+    struct XenFB *fb;
+    struct XenInput *in;
+    int i = 0;
+
+wait_more:
+    i++;
+    main_loop_wait(10); /* miliseconds */
+    xfb = xen_be_find_xendev("vfb", domid, 0);
+    xin = xen_be_find_xendev("vkbd", domid, 0);
+    if (!xfb || !xin) {
+        if (i < 256)
+            goto wait_more;
+        fprintf(stderr, "%s: displaystate setup failed\n", __FUNCTION__);
+        return;
+    }
 
-    xendev = xen_be_find_xendev(type, domid, 0);
-    if (!xendev)
-       return;
-    c = container_of(xendev, struct common, xendev);
-    c->ds = ds;
-    xen_be_printf(xendev, 1, "ds is %p\n", ds);
-    /* retry ->init() */
-    xen_be_check_state(xendev);
-}
+    /* vfb */
+    fb = container_of(xfb, struct XenFB, c.xendev);
+    fb->c.ds = graphic_console_init(xenfb_update,
+                                    xenfb_invalidate,
+                                    NULL,
+                                    NULL,
+                                    fb);
+    fb->have_console = 1;
 
-void xen_set_display(int domid)
-{
-    struct XenDevice *xendev = xen_be_find_xendev("vfb", domid, 0);
-    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);
-    DisplayState *ds = graphic_console_init(xenfb_update,
-            xenfb_invalidate,
-            NULL,
-            NULL,
-            fb);
-
-    xen_set_display_type(domid, "vkbd", ds);
-    xen_set_display_type(domid, "vfb", ds);
+    /* vkbd */
+    in = container_of(xin, struct XenInput, c.xendev);
+    in->c.ds = fb->c.ds;
+
+    /* retry ->init() */
+    xen_be_check_state(xin);
+    xen_be_check_state(xfb);
 }
-- 
1.6.2.2


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.