This patch merges the public & private structs from the paravirt FB
into a single struct. Since QEMU is the only consumer of this code
there is no need for the artifical pub/priv split. Merging the two
will make it possible to more tightly integrate with QEMU's event
loop and do asynchronous non-blocking negoiation with the frontend
devices (see next patch).
xenfb.c | 273 ++++++++++++++++++++++++++++++++--------------------------------
xenfb.h | 16 ---
2 files changed, 139 insertions(+), 150 deletions(-)
Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx>
Dan.
diff -r 231a22d0b7dd tools/ioemu/hw/xenfb.c
--- a/tools/ioemu/hw/xenfb.c Tue Aug 21 22:04:29 2007 -0400
+++ b/tools/ioemu/hw/xenfb.c Tue Aug 21 22:07:36 2007 -0400
@@ -22,6 +22,8 @@
// FIXME defend against malicious frontend?
+struct xenfb;
+
struct xenfb_device {
const char *devicetype;
char nodename[64]; /* backend xenstore dir */
@@ -30,20 +32,33 @@ struct xenfb_device {
enum xenbus_state state; /* backend state */
void *page; /* shared page */
evtchn_port_t port;
- struct xenfb_private *xenfb;
+ struct xenfb *xenfb;
};
-struct xenfb_private {
- struct xenfb pub;
+struct xenfb_data
+{
+ void *pixels;
+ size_t len;
+
+ int row_stride;
+ int depth;
+ int width;
+ int height;
+ int abs_pointer_wanted;
+};
+
+struct xenfb {
+ DisplayState *ds;
int evt_xch; /* event channel driver handle */
int xc; /* hypervisor interface handle */
struct xs_handle *xsh; /* xs daemon handle */
struct xenfb_device fb, kbd;
- size_t fb_len; /* size of framebuffer */
+ struct xenfb_data data;
char protocol[64]; /* frontend protocol */
+ int button_state;
};
-static void xenfb_detach_dom(struct xenfb_private *);
+static void xenfb_detach_dom(struct xenfb *);
static char *xenfb_path_in_dom(struct xs_handle *xsh,
char *buf, size_t size,
@@ -124,7 +139,7 @@ static int xenfb_xs_printf(struct xs_han
static void xenfb_device_init(struct xenfb_device *dev,
const char *type,
- struct xenfb_private *xenfb)
+ struct xenfb *xenfb)
{
dev->devicetype = type;
dev->otherend_id = -1;
@@ -132,19 +147,17 @@ static void xenfb_device_init(struct xen
dev->xenfb = xenfb;
}
-int xenfb_device_set_domain(struct xenfb_device *dev, int domid)
-{
- struct xenfb_private *xenfb = dev->xenfb;
-
+static int xenfb_device_set_domain(struct xenfb_device *dev, int domid)
+{
dev->otherend_id = domid;
- if (!xenfb_path_in_dom(xenfb->xsh,
+ if (!xenfb_path_in_dom(dev->xenfb->xsh,
dev->otherend, sizeof(dev->otherend),
domid, "device/%s/0", dev->devicetype)) {
errno = ENOENT;
return -1;
}
- if (!xenfb_path_in_dom(xenfb->xsh,
+ if (!xenfb_path_in_dom(dev->xenfb->xsh,
dev->nodename, sizeof(dev->nodename),
0, "backend/%s/%d/0", dev->devicetype, domid)) {
errno = ENOENT;
@@ -156,8 +169,8 @@ int xenfb_device_set_domain(struct xenfb
struct xenfb *xenfb_new(void)
{
- struct xenfb_private *xenfb = malloc(sizeof(*xenfb));
int serrno;
+ struct xenfb *xenfb = qemu_malloc(sizeof(struct xenfb));
if (xenfb == NULL)
return NULL;
@@ -179,30 +192,26 @@ struct xenfb *xenfb_new(void)
if (!xenfb->xsh)
goto fail;
- return &xenfb->pub;
+ return xenfb;
fail:
serrno = errno;
- xenfb_delete(&xenfb->pub);
+ xenfb_delete(xenfb);
errno = serrno;
return NULL;
}
/* Remove the backend area in xenbus since the framebuffer really is
going away. */
-void xenfb_teardown(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
-
+void xenfb_teardown(struct xenfb *xenfb)
+{
xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);
xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);
}
-void xenfb_delete(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
-
+void xenfb_delete(struct xenfb *xenfb)
+{
xenfb_detach_dom(xenfb);
if (xenfb->xc >= 0)
xc_interface_close(xenfb->xc);
@@ -334,7 +343,7 @@ static void xenfb_copy_mfns(int mode, in
dst[i] = (mode == 32) ? src32[i] : src64[i];
}
-static int xenfb_map_fb(struct xenfb_private *xenfb, int domid)
+static int xenfb_map_fb(struct xenfb *xenfb, int domid)
{
struct xenfb_page *page = xenfb->fb.page;
int n_fbmfns;
@@ -389,7 +398,7 @@ static int xenfb_map_fb(struct xenfb_pri
#endif
}
- n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
+ n_fbmfns = (xenfb->data.len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
n_fbdirs = n_fbmfns * mode / 8;
n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
@@ -412,9 +421,9 @@ static int xenfb_map_fb(struct xenfb_pri
xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
munmap(map, n_fbdirs * XC_PAGE_SIZE);
- xenfb->pub.pixels = xc_map_foreign_batch(xenfb->xc, domid,
+ xenfb->data.pixels = xc_map_foreign_batch(xenfb->xc, domid,
PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
- if (xenfb->pub.pixels == NULL)
+ if (xenfb->data.pixels == NULL)
goto out;
ret = 0; /* all is fine */
@@ -429,7 +438,7 @@ static int xenfb_map_fb(struct xenfb_pri
static int xenfb_bind(struct xenfb_device *dev)
{
- struct xenfb_private *xenfb = dev->xenfb;
+ struct xenfb *xenfb = dev->xenfb;
unsigned long mfn;
evtchn_port_t evtchn;
@@ -512,17 +521,74 @@ static void xenfb_dev_fatal(struct xenfb
}
-static void xenfb_detach_dom(struct xenfb_private *xenfb)
+static void xenfb_detach_dom(struct xenfb *xenfb)
{
xenfb_unbind(&xenfb->fb);
xenfb_unbind(&xenfb->kbd);
- if (xenfb->pub.pixels) {
- munmap(xenfb->pub.pixels, xenfb->fb_len);
- xenfb->pub.pixels = NULL;
- }
-}
-
-static void xenfb_on_fb_event(struct xenfb_private *xenfb)
+ if (xenfb->data.pixels) {
+ munmap(xenfb->data.pixels, xenfb->data.len);
+ xenfb->data.pixels = NULL;
+ }
+}
+
+/* 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->data.pixels +
(line*xenfb->data.row_stride) + (x*xenfb->data.depth/8)); \
+ DST_T *dst = (DST_T *)(xenfb->ds->data +
(line*xenfb->ds->linesize) + (x*xenfb->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 xenfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h)
+{
+ int line;
+
+ if (xenfb->data.depth == xenfb->ds->depth) { /* Perfect match can use
fast path */
+ for (line = y ; line < (y+h) ; line++) {
+ memcpy(xenfb->ds->data + (line * xenfb->ds->linesize) +
(x*xenfb->ds->depth/8),
+ xenfb->data.pixels +
(line*xenfb->data.row_stride) + (x*xenfb->data.depth/8),
+ w * xenfb->data.depth/8);
+ }
+ } else { /* Mismatch requires slow pixel munging */
+ if (xenfb->data.depth == 8) {
+ /* 8 bit source == r:3 g:3 b:2 */
+ if (xenfb->ds->depth == 16) {
+ BLT(uint8_t, uint16_t, 5, 2, 0, 11, 5, 0,
7, 7, 3);
+ } else if (xenfb->ds->depth == 32) {
+ BLT(uint8_t, uint32_t, 5, 2, 0, 16, 8, 0,
7, 7, 3);
+ }
+ } else if (xenfb->data.depth == 16) {
+ /* 16 bit source == r:5 g:6 b:5 */
+ if (xenfb->ds->depth == 8) {
+ BLT(uint16_t, uint8_t, 11, 5, 0, 5, 2, 0,
31, 63, 31);
+ } else if (xenfb->ds->depth == 32) {
+ BLT(uint16_t, uint32_t, 11, 5, 0, 16, 8, 0,
31, 63, 31);
+ }
+ } else if (xenfb->data.depth == 32) {
+ /* 32 bit source == r:8 g:8 b:8 (padding:8) */
+ if (xenfb->ds->depth == 8) {
+ BLT(uint32_t, uint8_t, 16, 8, 0, 5, 2, 0,
255, 255, 255);
+ } else if (xenfb->ds->depth == 16) {
+ BLT(uint32_t, uint16_t, 16, 8, 0, 11, 5, 0,
255, 255, 255);
+ }
+ }
+ }
+ dpy_update(xenfb->ds, x, y, w, h);
+}
+
+static void xenfb_on_fb_event(struct xenfb *xenfb)
{
uint32_t prod, cons;
struct xenfb_page *page = xenfb->fb.page;
@@ -536,11 +602,10 @@ static void xenfb_on_fb_event(struct xen
switch (event->type) {
case XENFB_TYPE_UPDATE:
- if (xenfb->pub.update)
- xenfb->pub.update(&xenfb->pub,
- event->update.x, event->update.y,
- event->update.width,
event->update.height);
- break;
+ xenfb_guest_copy(xenfb,
+ event->update.x, event->update.y,
+ event->update.width,
event->update.height);
+ break;
}
}
mb(); /* ensure we're done with ring contents */
@@ -548,7 +613,7 @@ static void xenfb_on_fb_event(struct xen
xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
}
-static void xenfb_on_kbd_event(struct xenfb_private *xenfb)
+static void xenfb_on_kbd_event(struct xenfb *xenfb)
{
struct xenkbd_page *page = xenfb->kbd.page;
@@ -586,7 +651,7 @@ static int xenfb_on_state_change(struct
return 0;
}
-static int xenfb_kbd_event(struct xenfb_private *xenfb,
+static int xenfb_kbd_event(struct xenfb *xenfb,
union xenkbd_in_event *event)
{
uint32_t prod;
@@ -608,9 +673,8 @@ static int xenfb_kbd_event(struct xenfb_
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;
+static int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode)
+{
union xenkbd_in_event event;
memset(&event, 0, XENKBD_IN_EVENT_SIZE);
@@ -621,9 +685,8 @@ static int xenfb_send_key(struct xenfb *
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;
+static int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y)
+{
union xenkbd_in_event event;
memset(&event, 0, XENKBD_IN_EVENT_SIZE);
@@ -634,9 +697,8 @@ static int xenfb_send_motion(struct xenf
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;
+static int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y)
+{
union xenkbd_in_event event;
memset(&event, 0, XENKBD_IN_EVENT_SIZE);
@@ -660,11 +722,11 @@ static void xenfb_mouse_event(void *opaq
{
int i;
struct xenfb *xenfb = (struct xenfb*)opaque;
- DisplayState *ds = (DisplayState *)xenfb->user_data;
- if (xenfb->abs_pointer_wanted)
+
+ if (xenfb->data.abs_pointer_wanted)
xenfb_send_position(xenfb,
- dx*ds->width/0x7fff,
- dy*ds->height/0x7fff);
+ dx*xenfb->ds->width/0x7fff,
+ dy*xenfb->ds->height/0x7fff);
else
xenfb_send_motion(xenfb, dx, dy);
@@ -680,76 +742,19 @@ static void xenfb_mouse_event(void *opaq
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.
- */
-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 */
static void xenfb_update(void *opaque)
{
struct xenfb *xenfb = (struct xenfb *)opaque;
- xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
+ xenfb_guest_copy(xenfb, 0, 0, xenfb->data.width, xenfb->data.height);
}
/* QEMU display state changed, so refresh the framebuffer copy */
static void xenfb_invalidate(void *opaque)
{
struct xenfb *xenfb = (struct xenfb *)opaque;
- xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
+ xenfb_guest_copy(xenfb, 0, 0, xenfb->data.width, xenfb->data.height);
}
/* Screen dump is not used in Xen, so no need to impl this ? */
@@ -757,9 +762,9 @@ static void xenfb_screen_dump(void *opaq
-static void xenfb_dispatch_channel(void *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+static void xenfb_dispatch_channel(void *opaque)
+{
+ struct xenfb *xenfb = (struct xenfb *)opaque;
evtchn_port_t port;
port = xc_evtchn_pending(xenfb->evt_xch);
if (port == -1)
@@ -774,9 +779,9 @@ static void xenfb_dispatch_channel(void
exit(1);
}
-static void xenfb_dispatch_store(void *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+static void xenfb_dispatch_store(void *opaque)
+{
+ struct xenfb *xenfb = (struct xenfb *)opaque;
unsigned dummy;
char **vec;
int r;
@@ -791,9 +796,8 @@ static void xenfb_dispatch_store(void *x
}
-int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid, DisplayState *ds)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+int xenfb_attach_dom(struct xenfb *xenfb, int domid, DisplayState *ds)
+{
struct xs_handle *xsh = xenfb->xsh;
int val, serrno;
struct xenfb_page *fb_page;
@@ -849,12 +853,12 @@ int xenfb_attach_dom(struct xenfb *xenfb
/* TODO check for permitted ranges */
fb_page = xenfb->fb.page;
- xenfb->pub.depth = fb_page->depth;
- xenfb->pub.width = fb_page->width;
- xenfb->pub.height = fb_page->height;
+ xenfb->data.depth = fb_page->depth;
+ xenfb->data.width = fb_page->width;
+ xenfb->data.height = fb_page->height;
/* TODO check for consistency with the above */
- xenfb->fb_len = fb_page->mem_length;
- xenfb->pub.row_stride = fb_page->line_length;
+ xenfb->data.len = fb_page->mem_length;
+ xenfb->data.row_stride = fb_page->line_length;
if (xenfb_map_fb(xenfb, domid) < 0)
goto error;
@@ -869,7 +873,7 @@ int xenfb_attach_dom(struct xenfb *xenfb
if (xenfb_xs_scanf1(xsh, xenfb->kbd.otherend, "request-abs-pointer",
"%d", &val) < 0)
val = 0;
- xenfb->pub.abs_pointer_wanted = val;
+ xenfb->data.abs_pointer_wanted = val;
/* Listen for events from xenstore */
if (qemu_set_fd_handler2(xs_fileno(xenfb->xsh), NULL,
xenfb_dispatch_store, NULL, xenfb) < 0)
@@ -882,19 +886,18 @@ int xenfb_attach_dom(struct xenfb *xenfb
/* Register our keyboard & mouse handlers */
qemu_add_kbd_event_handler(xenfb_put_keycode, xenfb);
qemu_add_mouse_event_handler(xenfb_mouse_event, xenfb,
- xenfb_pub->abs_pointer_wanted,
+ xenfb->data.abs_pointer_wanted,
"Xen PVFB Mouse");
- xenfb_pub->update = xenfb_guest_copy;
- xenfb_pub->user_data = ds;
+ xenfb->ds = 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);
+ xenfb);
+ dpy_resize(ds, xenfb->data.width, xenfb->data.height);
return 0;
diff -r 231a22d0b7dd tools/ioemu/hw/xenfb.h
--- a/tools/ioemu/hw/xenfb.h Tue Aug 21 22:04:29 2007 -0400
+++ b/tools/ioemu/hw/xenfb.h Tue Aug 21 22:04:43 2007 -0400
@@ -5,21 +5,7 @@
#include <stdbool.h>
#include <sys/types.h>
-struct xenfb
-{
- void *pixels;
-
- int row_stride;
- int depth;
- int width;
- int height;
- int abs_pointer_wanted;
- int button_state;
-
- void *user_data;
-
- void (*update)(struct xenfb *xenfb, int x, int y, int width, int
height);
-};
+struct xenfb;
struct xenfb *xenfb_new(void);
void xenfb_delete(struct xenfb *xenfb);
--
|=- 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 -=|
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|