All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrange" <berrange@redhat.com>
To: xen-devel@lists.xensource.com
Subject: Re: PATCH 5/10: Refactor QEMU console integration
Date: Wed, 24 Oct 2007 21:41:44 +0100	[thread overview]
Message-ID: <20071024204144.GI10807@redhat.com> (raw)
In-Reply-To: <20071024203513.GD10807@redhat.com>

This patch moves a bunch of code out of the xen_machine_pv.c file and into
the xenfb.c file. This is simply a re-factoring to facilitate the two patches
which follow.

 xen_machine_pv.c |  214 ---------------------------------
 xenfb.c          |  353 +++++++++++++++++++++++++++++++++++++++++++++----------
 xenfb.h          |    8 -
 3 files changed, 294 insertions(+), 281 deletions(-)

 Signed-off-by: Daniel P. Berrange <berrange@redhat.com>


diff -r 93300915575f tools/ioemu/hw/xen_machine_pv.c
--- a/tools/ioemu/hw/xen_machine_pv.c	Tue Sep 11 11:53:28 2007 -0400
+++ b/tools/ioemu/hw/xen_machine_pv.c	Tue Sep 11 11:53:34 2007 -0400
@@ -24,194 +24,6 @@
 
 #include "vl.h"
 #include "xenfb.h"
-#include <linux/input.h>
-
-/*
- * Tables to map from scancode to Linux input layer keycode.
- * Scancodes are hardware-specific.  These maps assumes a 
- * standard AT or PS/2 keyboard which is what QEMU feeds us.
- */
-static const unsigned char atkbd_set2_keycode[512] = {
-
-	  0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
-	  0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
-	  0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
-	  0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
-	  0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
-	  0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
-	  0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
-	 82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
-
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
-	173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
-	159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
-	157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
-	226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
-	110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
-
-};
-
-static const unsigned char atkbd_unxlate_table[128] = {
-
-	  0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
-	 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
-	 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
-	 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
-	 11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
-	114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
-	 71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
-	 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
-
-};
-
-static unsigned char scancode2linux[512];
-
-/* A convenient function for munging pixels between different depths */
-#define BLT(SRC_T,DST_T,RLS,GLS,BLS,RRS,GRS,BRS,RM,GM,BM)               \
-    for (line = y ; line < h ; line++) {                                \
-        SRC_T *src = (SRC_T *)(xenfb->pixels                            \
-                               + (line * xenfb->row_stride)             \
-                               + (x * xenfb->depth / 8));               \
-        DST_T *dst = (DST_T *)(ds->data                                 \
-                               + (line * ds->linesize)                  \
-                               + (x * ds->depth / 8));                  \
-        int col;                                                        \
-        for (col = x ; col < w ; col++) {                               \
-            *dst = (((*src >> RRS) & RM) << RLS) |                      \
-                (((*src >> GRS) & GM) << GLS) |                         \
-                (((*src >> GRS) & BM) << BLS);                          \
-            src++;                                                      \
-            dst++;                                                      \
-        }                                                               \
-    }
-
-/* 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.
- */
-static void xen_pvfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h)
-{
-    DisplayState *ds = (DisplayState *)xenfb->user_data;
-    int line;
-
-    if (xenfb->depth == ds->depth) { /* Perfect match can use fast path */
-        for (line = y ; line < (y+h) ; line++) {
-            memcpy(ds->data + (line * ds->linesize) + (x * ds->depth / 8),
-                   xenfb->pixels + (line * xenfb->row_stride) + (x * xenfb->depth / 8),
-                   w * xenfb->depth / 8);
-        }
-    } else { /* Mismatch requires slow pixel munging */
-        if (xenfb->depth == 8) {
-            /* 8 bit source == r:3 g:3 b:2 */
-            if (ds->depth == 16) {
-                BLT(uint8_t, uint16_t,   5, 2, 0,   11, 5, 0,   7, 7, 3);
-            } else if (ds->depth == 32) {
-                BLT(uint8_t, uint32_t,   5, 2, 0,   16, 8, 0,   7, 7, 3);
-            }
-        } else if (xenfb->depth == 16) {
-            /* 16 bit source == r:5 g:6 b:5 */
-            if (ds->depth == 8) {
-                BLT(uint16_t, uint8_t,    11, 5, 0,   5, 2, 0,    31, 63, 31);
-            } else if (ds->depth == 32) {
-                BLT(uint16_t, uint32_t,   11, 5, 0,   16, 8, 0,   31, 63, 31);
-            }
-        } else if (xenfb->depth == 32) {
-            /* 32 bit source == r:8 g:8 b:8 (padding:8) */
-            if (ds->depth == 8) {
-                BLT(uint32_t, uint8_t,    16, 8, 0,   5, 2, 0,    255, 255, 255);
-            } else if (ds->depth == 16) {
-                BLT(uint32_t, uint16_t,   16, 8, 0,   11, 5, 0,   255, 255, 255);
-            }
-        }
-    }
-    dpy_update(ds, x, y, w, h);
-}
-
-/* 
- * Send a key event from the client to the guest OS
- * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
- * We have to turn this into a Linux Input layer keycode.
- * 
- * Extra complexity from the fact that with extended scancodes 
- * (like those produced by arrow keys) this method gets called
- * twice, but we only want to send a single event. So we have to
- * track the '0xe0' scancode state & collapse the extended keys
- * as needed.
- * 
- * Wish we could just send scancodes straight to the guest which
- * already has code for dealing with this...
- */
-static void xen_pvfb_key_event(void *opaque, int scancode)
-{
-    static int extended = 0;
-    int down = 1;
-    if (scancode == 0xe0) {
-        extended = 1;
-        return;
-    } else if (scancode & 0x80) {
-        scancode &= 0x7f;
-        down = 0;
-    }
-    if (extended) {
-        scancode |= 0x80;
-        extended = 0;
-    }
-    xenfb_send_key(opaque, down, scancode2linux[scancode]);
-}
-
-/*
- * Send a mouse event from the client to the guest OS
- * 
- * The QEMU mouse can be in either relative, or absolute mode.
- * Movement is sent separately from button state, which has to
- * be encoded as virtual key events. We also don't actually get
- * given any button up/down events, so have to track changes in
- * the button state.
- */
-static void xen_pvfb_mouse_event(void *opaque,
-                                 int dx, int dy, int dz, int button_state)
-{
-    static int old_state = 0;
-    int i;
-    struct xenfb *xenfb = opaque;
-    DisplayState *ds = (DisplayState *)xenfb->user_data;
-    if (xenfb->abs_pointer_wanted)
-        xenfb_send_position(xenfb,
-                            dx * ds->width / 0x7fff,
-                            dy * ds->height / 0x7fff);
-    else
-        xenfb_send_motion(xenfb, dx, dy);
-
-	for (i = 0 ; i < 8 ; i++) {
-		int lastDown = old_state & (1 << i);
-		int down = button_state & (1 << i);
-		if (down == lastDown)
-			continue;
-
-		if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
-			return;
-	}
-    old_state = button_state;
-}
-
-/* QEMU display state changed, so refresh the framebuffer copy */
-/* XXX - can we optimize this, or the next func at all ? */ 
-void xen_pvfb_update(void *opaque)
-{
-    struct xenfb *xenfb = opaque;
-    xen_pvfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
-}
-
-/* QEMU display state changed, so refresh the framebuffer copy */
-void xen_pvfb_invalidate(void *opaque)
-{
-    xen_pvfb_update(opaque);
-}
-
-/* Screen dump is not used in Xen, so no need to impl this ? */
-void xen_pvfb_screen_dump(void *opaque, const char *name) { }
 
 /* The Xen PV machine currently provides
  *   - a virtual framebuffer
@@ -226,14 +38,6 @@ static void xen_init_pv(uint64_t ram_siz
 {
     struct xenfb *xenfb;
     extern int domid;
-    int i;
-
-    /* Prepare scancode mapping table */
-	for (i = 0; i < 128; i++) {
-		scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
-		scancode2linux[i | 0x80] = 
-			atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
-	}
 
     /* Prepare PVFB state */
     xenfb = xenfb_new();
@@ -244,27 +48,11 @@ static void xen_init_pv(uint64_t ram_siz
     }
 
     /* Talk to the guest */
-    if (xenfb_attach_dom(xenfb, domid) < 0) {
+    if (xenfb_attach_dom(xenfb, domid, ds) < 0) {
         fprintf(stderr, "Could not connect to domain (%s)\n",
                 strerror(errno));
         exit(1);
     }
-    xenfb->update = xen_pvfb_guest_copy;
-    xenfb->user_data = ds;
-
-    /* Tell QEMU to allocate a graphical console */
-    graphic_console_init(ds,
-                         xen_pvfb_update,
-                         xen_pvfb_invalidate,
-                         xen_pvfb_screen_dump,
-                         xenfb);
-
-    /* Register our keyboard & mouse handlers */
-    qemu_add_kbd_event_handler(xen_pvfb_key_event, xenfb);
-    qemu_add_mouse_event_handler(xen_pvfb_mouse_event, xenfb,
-                                 xenfb->abs_pointer_wanted,
-                                 "Xen PVFB Mouse");
-
 
     /* Setup QEMU display */
     dpy_resize(ds, xenfb->width, xenfb->height);
diff -r 93300915575f tools/ioemu/hw/xenfb.c
--- a/tools/ioemu/hw/xenfb.c	Tue Sep 11 11:53:28 2007 -0400
+++ b/tools/ioemu/hw/xenfb.c	Tue Sep 11 11:53:34 2007 -0400
@@ -16,8 +16,8 @@
 #include <string.h>
 #include <time.h>
 #include <xs.h>
-
-#include "vl.h"
+#include <linux/input.h>
+
 #include "xenfb.h"
 
 // FIXME defend against malicious frontend?
@@ -43,6 +43,58 @@ struct xenfb_private {
 	char protocol[64];	/* frontend protocol */
 };
 
+/* Functions which tie the PVFB into the QEMU device model */
+static void xenfb_key_event(void *opaque, int keycode);
+static void xenfb_mouse_event(void *opaque,
+			      int dx, int dy, int dz, int button_state);
+static void xenfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h);
+static void xenfb_update(void *opaque);
+static void xenfb_invalidate(void *opaque);
+static void xenfb_screen_dump(void *opaque, const char *name);
+
+/*
+ * Tables to map from scancode to Linux input layer keycode.
+ * Scancodes are hardware-specific.  These maps assumes a 
+ * standard AT or PS/2 keyboard which is what QEMU feeds us.
+ */
+static const unsigned char atkbd_set2_keycode[512] = {
+
+	  0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
+	  0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
+	  0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
+	  0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
+	  0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
+	  0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
+	  0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
+	 82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
+
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
+	173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
+	159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
+	157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
+	226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
+	110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
+
+};
+
+static const unsigned char atkbd_unxlate_table[128] = {
+
+	  0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
+	 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
+	 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
+	 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
+	 11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
+	114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
+	 71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
+	 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
+
+};
+
+static unsigned char scancode2linux[512];
+
+
 static void xenfb_detach_dom(struct xenfb_private *);
 
 static char *xenfb_path_in_dom(struct xs_handle *xsh,
@@ -158,9 +210,17 @@ struct xenfb *xenfb_new(void)
 {
 	struct xenfb_private *xenfb = malloc(sizeof(*xenfb));
 	int serrno;
+	int i;
 
 	if (xenfb == NULL)
 		return NULL;
+
+	/* Prepare scancode mapping table */
+	for (i = 0; i < 128; i++) {
+		scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
+		scancode2linux[i | 0x80] = 
+			atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
+	}
 
 	memset(xenfb, 0, sizeof(*xenfb));
 	xenfb->evt_xch = xenfb->xc = -1;
@@ -580,6 +640,68 @@ static int xenfb_on_state_change(struct 
 	return 0;
 }
 
+static int xenfb_kbd_event(struct xenfb_private *xenfb,
+			   union xenkbd_in_event *event)
+{
+	uint32_t prod;
+	struct xenkbd_page *page = xenfb->kbd.page;
+
+	if (xenfb->kbd.state != XenbusStateConnected)
+		return 0;
+
+	prod = page->in_prod;
+	if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
+		errno = EAGAIN;
+		return -1;
+	}
+
+	mb();			/* ensure ring space available */
+	XENKBD_IN_RING_REF(page, prod) = *event;
+	wmb();			/* ensure ring contents visible */
+	page->in_prod = prod + 1;
+	return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
+}
+
+static int xenfb_send_key(struct xenfb *xenfb_pub, bool down, int keycode)
+{
+	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+	union xenkbd_in_event event;
+
+	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+	event.type = XENKBD_TYPE_KEY;
+	event.key.pressed = down ? 1 : 0;
+	event.key.keycode = keycode;
+
+	return xenfb_kbd_event(xenfb, &event);
+}
+
+static int xenfb_send_motion(struct xenfb *xenfb_pub, int rel_x, int rel_y)
+{
+	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+	union xenkbd_in_event event;
+
+	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+	event.type = XENKBD_TYPE_MOTION;
+	event.motion.rel_x = rel_x;
+	event.motion.rel_y = rel_y;
+
+	return xenfb_kbd_event(xenfb, &event);
+}
+
+static int xenfb_send_position(struct xenfb *xenfb_pub, int abs_x, int abs_y)
+{
+	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+	union xenkbd_in_event event;
+
+	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+	event.type = XENKBD_TYPE_POS;
+	event.pos.abs_x = abs_x;
+	event.pos.abs_y = abs_y;
+
+	return xenfb_kbd_event(xenfb, &event);
+}
+
+
 static void xenfb_dispatch_channel(void *xenfb_pub)
 {
 	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
@@ -614,7 +736,7 @@ static void xenfb_dispatch_store(void *x
 }
 
 
-int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
+int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid, DisplayState *ds)
 {
 	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
 	struct xs_handle *xsh = xenfb->xsh;
@@ -702,6 +824,23 @@ int xenfb_attach_dom(struct xenfb *xenfb
 	if (qemu_set_fd_handler2(xc_evtchn_fd(xenfb->evt_xch), NULL, xenfb_dispatch_channel, NULL, xenfb) < 0)
 		goto error;
 
+	/* Register our keyboard & mouse handlers */
+	qemu_add_kbd_event_handler(xenfb_key_event, xenfb);
+	qemu_add_mouse_event_handler(xenfb_mouse_event, xenfb,
+				     xenfb_pub->abs_pointer_wanted,
+				     "Xen PVFB Mouse");
+
+	xenfb_pub->update = xenfb_guest_copy;
+	xenfb_pub->user_data = ds;
+
+	/* Tell QEMU to allocate a graphical console */
+	graphic_console_init(ds,
+			     xenfb_update,
+			     xenfb_invalidate,
+			     xenfb_screen_dump,
+			     xenfb_pub);
+	dpy_resize(ds, xenfb_pub->width, xenfb_pub->height);
+
 	return 0;
 
  error:
@@ -713,66 +852,154 @@ int xenfb_attach_dom(struct xenfb *xenfb
         return -1;
 }
 
-static int xenfb_kbd_event(struct xenfb_private *xenfb,
-			   union xenkbd_in_event *event)
-{
-	uint32_t prod;
-	struct xenkbd_page *page = xenfb->kbd.page;
-
-	if (xenfb->kbd.state != XenbusStateConnected)
-		return 0;
-
-	prod = page->in_prod;
-	if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
-		errno = EAGAIN;
-		return -1;
-	}
-
-	mb();			/* ensure ring space available */
-	XENKBD_IN_RING_REF(page, prod) = *event;
-	wmb();			/* ensure ring contents visible */
-	page->in_prod = prod + 1;
-	return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
-}
-
-int xenfb_send_key(struct xenfb *xenfb_pub, bool down, int keycode)
-{
-	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
-	union xenkbd_in_event event;
-
-	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
-	event.type = XENKBD_TYPE_KEY;
-	event.key.pressed = down ? 1 : 0;
-	event.key.keycode = keycode;
-
-	return xenfb_kbd_event(xenfb, &event);
-}
-
-int xenfb_send_motion(struct xenfb *xenfb_pub, int rel_x, int rel_y)
-{
-	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
-	union xenkbd_in_event event;
-
-	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
-	event.type = XENKBD_TYPE_MOTION;
-	event.motion.rel_x = rel_x;
-	event.motion.rel_y = rel_y;
-
-	return xenfb_kbd_event(xenfb, &event);
-}
-
-int xenfb_send_position(struct xenfb *xenfb_pub, int abs_x, int abs_y)
-{
-	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
-	union xenkbd_in_event event;
-
-	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
-	event.type = XENKBD_TYPE_POS;
-	event.pos.abs_x = abs_x;
-	event.pos.abs_y = abs_y;
-
-	return xenfb_kbd_event(xenfb, &event);
-}
+/* 
+ * Send a key event from the client to the guest OS
+ * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
+ * We have to turn this into a Linux Input layer keycode.
+ * 
+ * Extra complexity from the fact that with extended scancodes 
+ * (like those produced by arrow keys) this method gets called
+ * twice, but we only want to send a single event. So we have to
+ * track the '0xe0' scancode state & collapse the extended keys
+ * as needed.
+ * 
+ * Wish we could just send scancodes straight to the guest which
+ * already has code for dealing with this...
+ */
+static void xenfb_key_event(void *opaque, int scancode)
+{
+    static int extended = 0;
+    int down = 1;
+    if (scancode == 0xe0) {
+        extended = 1;
+        return;
+    } else if (scancode & 0x80) {
+        scancode &= 0x7f;
+        down = 0;
+    }
+    if (extended) {
+        scancode |= 0x80;
+        extended = 0;
+    }
+    xenfb_send_key(opaque, down, scancode2linux[scancode]);
+}
+
+/*
+ * Send a mouse event from the client to the guest OS
+ * 
+ * The QEMU mouse can be in either relative, or absolute mode.
+ * Movement is sent separately from button state, which has to
+ * be encoded as virtual key events. We also don't actually get
+ * given any button up/down events, so have to track changes in
+ * the button state.
+ */
+static void xenfb_mouse_event(void *opaque,
+			      int dx, int dy, int dz, int button_state)
+{
+    int i;
+    struct xenfb *xenfb = opaque;
+    DisplayState *ds = (DisplayState *)xenfb->user_data;
+    if (xenfb->abs_pointer_wanted)
+	    xenfb_send_position(xenfb,
+				dx * ds->width / 0x7fff,
+				dy * ds->height / 0x7fff);
+    else
+	    xenfb_send_motion(xenfb, dx, dy);
+
+    for (i = 0 ; i < 8 ; i++) {
+	    int lastDown = xenfb->button_state & (1 << i);
+	    int down = button_state & (1 << i);
+	    if (down == lastDown)
+		    continue;
+
+	    if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
+		    return;
+    }
+    xenfb->button_state = button_state;
+}
+
+/* A convenient function for munging pixels between different depths */
+#define BLT(SRC_T,DST_T,RLS,GLS,BLS,RRS,GRS,BRS,RM,GM,BM)               \
+    for (line = y ; line < h ; line++) {                                \
+        SRC_T *src = (SRC_T *)(xenfb->pixels                            \
+                               + (line * xenfb->row_stride)             \
+                               + (x * xenfb->depth / 8));               \
+        DST_T *dst = (DST_T *)(ds->data                                 \
+                               + (line * ds->linesize)                  \
+                               + (x * ds->depth / 8));                  \
+        int col;                                                        \
+        for (col = x ; col < w ; col++) {                               \
+            *dst = (((*src >> RRS) & RM) << RLS) |                      \
+                (((*src >> GRS) & GM) << GLS) |                         \
+                (((*src >> GRS) & BM) << BLS);                          \
+            src++;                                                      \
+            dst++;                                                      \
+        }                                                               \
+    }
+
+
+/* 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.
+ */
+static void xenfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h)
+{
+    DisplayState *ds = (DisplayState *)xenfb->user_data;
+    int line;
+
+    if (xenfb->depth == ds->depth) { /* Perfect match can use fast path */
+        for (line = y ; line < (y+h) ; line++) {
+            memcpy(ds->data + (line * ds->linesize) + (x * ds->depth / 8),
+                   xenfb->pixels + (line * xenfb->row_stride) + (x * xenfb->depth / 8),
+                   w * xenfb->depth / 8);
+        }
+    } else { /* Mismatch requires slow pixel munging */
+        if (xenfb->depth == 8) {
+            /* 8 bit source == r:3 g:3 b:2 */
+            if (ds->depth == 16) {
+                BLT(uint8_t, uint16_t,   5, 2, 0,   11, 5, 0,   7, 7, 3);
+            } else if (ds->depth == 32) {
+                BLT(uint8_t, uint32_t,   5, 2, 0,   16, 8, 0,   7, 7, 3);
+            }
+        } else if (xenfb->depth == 16) {
+            /* 16 bit source == r:5 g:6 b:5 */
+            if (ds->depth == 8) {
+                BLT(uint16_t, uint8_t,    11, 5, 0,   5, 2, 0,    31, 63, 31);
+            } else if (ds->depth == 32) {
+                BLT(uint16_t, uint32_t,   11, 5, 0,   16, 8, 0,   31, 63, 31);
+            }
+        } else if (xenfb->depth == 32) {
+            /* 32 bit source == r:8 g:8 b:8 (padding:8) */
+            if (ds->depth == 8) {
+                BLT(uint32_t, uint8_t,    16, 8, 0,   5, 2, 0,    255, 255, 255);
+            } else if (ds->depth == 16) {
+                BLT(uint32_t, uint16_t,   16, 8, 0,   11, 5, 0,   255, 255, 255);
+            }
+        }
+    }
+    dpy_update(ds, x, y, w, h);
+}
+
+/* QEMU display state changed, so refresh the framebuffer copy */
+/* XXX - can we optimize this, or the next func at all ? */ 
+static void xenfb_update(void *opaque)
+{
+    struct xenfb *xenfb = opaque;
+    xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
+}
+
+/* QEMU display state changed, so refresh the framebuffer copy */
+static void xenfb_invalidate(void *opaque)
+{
+    struct xenfb *xenfb = opaque;
+    xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
+}
+
+/* Screen dump is not used in Xen, so no need to impl this....yet */
+static void xenfb_screen_dump(void *opaque, const char *name) { }
+
+
 /*
  * Local variables:
  *  c-indent-level: 8
diff -r 93300915575f tools/ioemu/hw/xenfb.h
--- a/tools/ioemu/hw/xenfb.h	Tue Sep 11 11:53:28 2007 -0400
+++ b/tools/ioemu/hw/xenfb.h	Tue Sep 11 11:53:34 2007 -0400
@@ -1,6 +1,7 @@
 #ifndef _XENFB_H_
 #define _XENFB_H_
 
+#include "vl.h"
 #include <stdbool.h>
 #include <sys/types.h>
 
@@ -13,6 +14,7 @@ struct xenfb
 	int width;
 	int height;
 	int abs_pointer_wanted;
+	int button_state;
 
 	void *user_data;
 
@@ -23,10 +25,6 @@ void xenfb_delete(struct xenfb *xenfb);
 void xenfb_delete(struct xenfb *xenfb);
 void xenfb_teardown(struct xenfb *xenfb);
 
-int xenfb_attach_dom(struct xenfb *xenfb, int domid);
-
-int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode);
-int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);
-int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y);
+int xenfb_attach_dom(struct xenfb *xenfb, int domid, DisplayState *ds);
 
 #endif

-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 

  parent reply	other threads:[~2007-10-24 20:41 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-24 20:35 PATCH 0/10: Merge PV framebuffer & console into QEMU Daniel P. Berrange
2007-10-24 20:39 ` PATCH 1/10: Add a QEMU machine type for fullvirt guests Daniel P. Berrange
2007-10-24 20:40 ` PATCH 2/10: Add a QEMU machine type for paravirt guests Daniel P. Berrange
2007-10-24 20:40 ` PATCH 3/10: Remove standalone xenfb code Daniel P. Berrange
2007-10-24 20:41 ` PATCH 4/10: Refactor xenfb event handlers Daniel P. Berrange
2007-10-24 20:41 ` Daniel P. Berrange [this message]
2007-10-24 20:42 ` PATCH 6/10: Merge private & public xenfb structs Daniel P. Berrange
2007-10-24 20:42 ` PATCH 7/10: Async negotiation with xenfb frontend Daniel P. Berrange
2007-10-24 20:43 ` PATCH 8/10: Add pv console to QEMU paravirt machine Daniel P. Berrange
2007-10-24 20:44 ` PATCH 9/10: XenD device model re-factoring Daniel P. Berrange
2007-10-24 20:44 ` PATCH 10/10: Make xenconsoled ignore doms with qemu-dm Daniel P. Berrange
2007-10-25 18:56 ` PATCH 0/10: Merge PV framebuffer & console into QEMU Alex Williamson
2007-10-25 19:02   ` Daniel P. Berrange
2007-10-25 21:23   ` Daniel P. Berrange
2007-10-25 21:41     ` Alex Williamson
2007-10-26  8:16       ` Markus Armbruster
2007-10-26 16:15       ` Daniel P. Berrange
  -- strict thread matches above, loose matches on Subject: below --
2007-08-22 22:26 PATCH: 0/10: Merge paravirt FB & console into qemu-dm Daniel P. Berrange
2007-08-22 22:31 ` PATCH: 5/10: Refactor QEMU console integration Daniel P. Berrange
2007-08-15 20:00 PATCH: 0/10: Merge xenfb & xenconsoled into qemu-dm Daniel P. Berrange
2007-08-15 20:07 ` PATCH: 5/10: Refactor QEMU console integration Daniel P. Berrange

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20071024204144.GI10807@redhat.com \
    --to=berrange@redhat.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.