From: Peter Dinda Date: Thu, 26 Apr 2012 23:01:12 +0000 (-0500) Subject: Implementation of host-driven rendering in graphics console X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=4d6bd085dfbca6d0749aab7a77e1ffd70f9467b7;p=palacios.releases.git Implementation of host-driven rendering in graphics console --- diff --git a/linux_module/iface-graphics-console.c b/linux_module/iface-graphics-console.c index 227e90e..70dede5 100644 --- a/linux_module/iface-graphics-console.c +++ b/linux_module/iface-graphics-console.c @@ -56,10 +56,17 @@ struct palacios_graphics_console { uint32_t num_updates; - // Currently keystrokes and mouse movements are ignored + int change_request; + + int (*render_request)(v3_graphics_console_t cons, + void *priv_data); + void *render_data; + + int (*update_inquire)(v3_graphics_console_t cons, + void *priv_data); + + void *update_data; - // currently, we will not worry about locking this - // lock_t ... }; @@ -189,21 +196,56 @@ static void g_release_data_rw(v3_graphics_console_t cons) static int g_changed(v3_graphics_console_t cons) { -#if 0 struct palacios_graphics_console *gc = (struct palacios_graphics_console *) cons; + int cr; + + cr = gc->change_request; + + gc->change_request=0; - int rc = !(gc->num_updates % 1000); - gc->num_updates++; - return rc; -#else - return 1; -#endif + return cr; + +} + + +static int g_register_render_request( + v3_graphics_console_t cons, + int (*render_request)(v3_graphics_console_t, + void *), + void *priv_data) +{ + struct palacios_graphics_console *gc = + (struct palacios_graphics_console *) cons; + + gc->render_data = priv_data; + gc->render_request = render_request; + + printk("palacios: installed rendering callback function for graphics console\n"); + + return 0; + } +static int g_register_update_inquire( + v3_graphics_console_t cons, + int (*update_inquire)(v3_graphics_console_t, + void *), + void *priv_data) +{ + struct palacios_graphics_console *gc = + (struct palacios_graphics_console *) cons; + + gc->update_data = priv_data; + gc->update_inquire = update_inquire; + + printk("palacios: installed update inquiry callback function for graphics console\n"); + + return 0; +} static int palacios_graphics_console_key(struct v3_guest * guest, struct palacios_graphics_console *cons, @@ -213,7 +255,11 @@ static int palacios_graphics_console_key(struct v3_guest * guest, e.status = 0; e.scan_code = scancode; + //printk("palacios: start key delivery\n"); + v3_deliver_keyboard_event(guest->v3_ctx, &e); + + //printk("palacios: end key delivery\n"); return 0; } @@ -227,7 +273,8 @@ static int palacios_graphics_console_mouse(struct v3_guest * guest, e.data[1]=y; e.data[2]=buttons; // These three are completely wrong, of course - ignoring mouse for now - v3_deliver_mouse_event(guest->v3_ctx,&e); + // mouse delivery is broken, so don't do it. + // v3_deliver_mouse_event(guest->v3_ctx,&e); return 0; } @@ -243,6 +290,8 @@ static struct v3_graphics_console_hooks palacios_graphics_console_hooks = .release_data_rw = g_release_data_rw, .changed = g_changed, + .register_render_request = g_register_render_request, + .register_update_inquire = g_register_update_inquire, }; @@ -268,15 +317,24 @@ static int fb_query(struct v3_guest * guest, unsigned int cmd, unsigned long arg switch (q.request_type) { case V3_FB_SPEC: + //printk("palacios: request for db spec from Userland\n"); // returns only the spec for the FB q.spec = cons->spec; break; case V3_FB_UPDATE: + //printk("palacios: test for fb updatei from Userland\n"); // returns whether an update is available for the region - // currently always true - q.updated = 1; + if (cons->update_inquire) { + q.updated = cons->update_inquire(cons,cons->update_data); + } else { + q.updated = 1; + } + //printk("palacios: update=%d\n",q.updated); + + // request a render, since a FB_DATA will probably soon come + cons->change_request = 1; break; @@ -290,18 +348,28 @@ static int fb_query(struct v3_guest * guest, unsigned int cmd, unsigned long arg break; case V3_FB_DATA_ALL: { + //printk("palacios: got FrameBuffer Request from Userland\n"); // First let's sanity check to see if they are requesting the same // spec that we have if (memcmp(&(q.spec),&(cons->spec),sizeof(struct v3_frame_buffer_spec))) { printk("palacios: request for data with non-matching fb spec \n"); return -EFAULT; } + // Now we will force a render if we can + if (cons->render_request) { + //printk("palacios: making rendering request\n"); + cons->render_request(cons,cons->render_data); + } + // Now let's indicate an update is in the pointer and copy across the data if (copy_to_user(q.data,cons->data,cons->spec.width*cons->spec.height*cons->spec.bytes_per_pixel)) { printk("palacios: unable to copy fb content to user\n"); return -EFAULT; } + //printk("palacios: FrameBuffer copy out done\n"); q.updated = 1; + // Now we don't need to request a render + cons->change_request = 0; } break; @@ -333,19 +401,24 @@ static int fb_input(struct v3_guest * guest, printk("palacios: copy from user in getting input in fb\n"); return -EFAULT; } + + //printk("palacios: input from Userland\n"); if ((inp.data_type == V3_FB_KEY) || (inp.data_type == V3_FB_BOTH)) { rc = palacios_graphics_console_key(guest, cons, inp.scan_code); + //printk("palacios: key delivered to palacios\n"); } if ((inp.data_type == V3_FB_MOUSE) || (inp.data_type == V3_FB_BOTH)) { rc |= palacios_graphics_console_mouse(guest, cons, inp.mouse_data[0], inp.mouse_data[1], inp.mouse_data[2]); + //printk("palacios: mouse delivered to palacios\n"); } if (rc) { return -EFAULT; } else { + cons->change_request=1; return 0; } } diff --git a/palacios/include/interfaces/vmm_graphics_console.h b/palacios/include/interfaces/vmm_graphics_console.h index 7cdd427..649b532 100644 --- a/palacios/include/interfaces/vmm_graphics_console.h +++ b/palacios/include/interfaces/vmm_graphics_console.h @@ -47,6 +47,19 @@ void *v3_graphics_console_get_frame_buffer_data_rw(v3_graphics_console_t cons, s void v3_graphics_console_release_frame_buffer_data_rw(v3_graphics_console_t cons); // returns >0 if a redraw in response to this update would be useful now int v3_graphics_console_inform_update(v3_graphics_console_t cons); +// when render_request is invoked, Palacios will redraw immediately +int v3_graphics_console_register_render_request( + v3_graphics_console_t cons, + int (*render_request)(v3_graphics_console_t cons, + void *priv_data), + void *priv_data); +// when update_inquire is invoked, palacios will indicate if there +// is anything new with a non-zero return value +int v3_graphics_console_register_update_inquire( + v3_graphics_console_t cons, + int (*update_inquire)(v3_graphics_console_t cons, + void *priv_data), + void *priv_data); void v3_graphics_console_close(v3_graphics_console_t cons); @@ -87,7 +100,27 @@ struct v3_graphics_console_hooks { // callback to indicate that the FB is stale and that an update can occur // a positive return value indicates we should re-render now + // this callback is from Palacios to the implementation and is called + // when virtual GPU state changes to ask if the FB should be re-rendered now int (*changed)(v3_graphics_console_t cons); + + + // callback to allow Palacios to register a render request callback + // with the implementation. Using this callback, the implementation + // can specifically request that Palacios render immediately + int (*register_render_request)(v3_graphics_console_t cons, + int (*render_request)(v3_graphics_console_t cons, + void *priv_data), + void *priv_data); + + // callback to allow Palacios to register an update inquire callback + // with the implementation. Using this callback, the implementation + // can ask if Palacios has any new data + int (*register_update_inquire)(v3_graphics_console_t cons, + int (*update_inquire)(v3_graphics_console_t cons, + void *priv_data), + void *priv_data); + }; diff --git a/palacios/src/interfaces/vmm_graphics_console.c b/palacios/src/interfaces/vmm_graphics_console.c index 9eba2de..3857f65 100644 --- a/palacios/src/interfaces/vmm_graphics_console.c +++ b/palacios/src/interfaces/vmm_graphics_console.c @@ -86,6 +86,31 @@ int v3_graphics_console_inform_update(v3_graphics_console_t cons) { return graphics_console_hooks->changed(cons); } +int v3_graphics_console_register_render_request( + v3_graphics_console_t cons, + int (*render_request)(v3_graphics_console_t cons, + void *priv_data), + void *priv_data) +{ + V3_ASSERT(graphics_console_hooks!=NULL); + V3_ASSERT(graphics_console_hooks->register_render_request!=NULL); + + return graphics_console_hooks->register_render_request(cons,render_request,priv_data); +} + +int v3_graphics_console_register_update_inquire( + v3_graphics_console_t cons, + int (*update_inquire)(v3_graphics_console_t cons, + void *priv_data), + void *priv_data) +{ + V3_ASSERT(graphics_console_hooks!=NULL); + V3_ASSERT(graphics_console_hooks->register_update_inquire!=NULL); + + return graphics_console_hooks->register_update_inquire(cons,update_inquire,priv_data); +} + + void V3_Init_Graphics_Console(struct v3_graphics_console_hooks * hooks) { graphics_console_hooks = hooks; PrintDebug("V3 graphics console inited\n");