/* * Periodic update of display. * Also transmit the refresh interval to the frontend. * * Never ever do any qemu display operations * (resize, screen update) outside this function. * Our screen might be inactive. When asked for * an update we know it is active. */ static void xenfb_update(void *opaque) { struct XenFB *xenfb = opaque; DisplaySurface *surface; int i; if (xenfb->c.xendev.be_state != XenbusStateConnected) return; if (!xenfb->feature_update) { /* we don't get update notifications, thus use the * sledge hammer approach ... */ xenfb->up_fullscreen = 1; } /* resize if needed */ if (xenfb->do_resize) { pixman_format_code_t format; xenfb->do_resize = 0; switch (xenfb->depth) { case 16: case 32: /* console.c supported depth -> buffer can be used directly */ format = qemu_default_pixman_format(xenfb->depth, true); surface = qemu_create_displaysurface_from (xenfb->width, xenfb->height, format, xenfb->row_stride, xenfb->pixels + xenfb->offset); break; default: /* we must convert stuff */ surface = qemu_create_displaysurface(xenfb->width, xenfb->height); break; } dpy_gfx_replace_surface(xenfb->c.con, surface); xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n", xenfb->width, xenfb->height, xenfb->depth, is_buffer_shared(surface) ? " (shared)" : ""); xenfb->up_fullscreen = 1; } /* run queued updates */ if (xenfb->up_fullscreen) { xen_be_printf(&xenfb->c.xendev, 3, "update: fullscreen\n"); xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height); } else if (xenfb->up_count) { xen_be_printf(&xenfb->c.xendev, 3, "update: %d rects\n", xenfb->up_count); for (i = 0; i < xenfb->up_count; i++) xenfb_guest_copy(xenfb, xenfb->up_rects[i].x, xenfb->up_rects[i].y, xenfb->up_rects[i].w, xenfb->up_rects[i].h); } else { xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n"); } xenfb->up_count = 0; xenfb->up_fullscreen = 0; }
static void xenfb_on_fb_event(struct xenfb *xenfb) { uint32_t prod, cons; struct xenfb_page *page = xenfb->fb.page; prod = page->out_prod; if (prod == page->out_cons) return; xen_rmb(); /* ensure we see ring contents up to prod */ for (cons = page->out_cons; cons != prod; cons++) { union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons); int x, y, w, h; switch (event->type) { case XENFB_TYPE_UPDATE: x = MAX(event->update.x, 0); y = MAX(event->update.y, 0); w = MIN(event->update.width, xenfb->width - x); h = MIN(event->update.height, xenfb->height - y); if (w < 0 || h < 0) { fprintf(stderr, "%s bogus update ignored\n", xenfb->fb.nodename); break; } if (x != event->update.x || y != event->update.y || w != event->update.width || h != event->update.height) { fprintf(stderr, "%s bogus update clipped\n", xenfb->fb.nodename); } xenfb_guest_copy(xenfb, x, y, w, h); break; case XENFB_TYPE_RESIZE: if (xenfb_configure_fb(xenfb, xenfb->fb_len, event->resize.width, event->resize.height, event->resize.depth, xenfb->fb_len, event->resize.offset, event->resize.stride) < 0) break; if (xenfb->ds->dpy_resize_shared) dpy_resize_shared(xenfb->ds, xenfb->width, xenfb->height, xenfb->depth, xenfb->row_stride, xenfb->pixels + xenfb->offset); else dpy_resize(xenfb->ds, xenfb->width, xenfb->height); xenfb_invalidate(xenfb); break; } } xen_mb(); /* ensure we're done with ring contents */ page->out_cons = cons; xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); }
static void xenfb_on_fb_event(struct xenfb *xenfb) { uint32_t prod, cons; struct xenfb_page *page = xenfb->fb.page; prod = page->out_prod; if (prod == page->out_cons) return; rmb(); /* ensure we see ring contents up to prod */ for (cons = page->out_cons; cons != prod; cons++) { union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons); int x, y, w, h; switch (event->type) { case XENFB_TYPE_UPDATE: x = MAX(event->update.x, 0); y = MAX(event->update.y, 0); w = MIN(event->update.width, xenfb->width - x); h = MIN(event->update.height, xenfb->height - y); if (w < 0 || h < 0) { fprintf(stderr, "%s bogus update ignored\n", xenfb->fb.nodename); break; } if (x != event->update.x || y != event->update.y || w != event->update.width || h != event->update.height) { fprintf(stderr, "%s bogus update clipped\n", xenfb->fb.nodename); break; } xenfb_guest_copy(xenfb, x, y, w, h); break; } } mb(); /* ensure we're done with ring contents */ page->out_cons = cons; xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); }
/* * Periodic update of display. * Also transmit the refresh interval to the frontend. * * Never ever do any qemu display operations * (resize, screen update) outside this function. * Our screen might be inactive. When asked for * an update we know it is active. */ static void xenfb_update(void *opaque) { struct XenFB *xenfb = opaque; struct DisplayChangeListener *l; int i; if (xenfb->c.xendev.be_state != XenbusStateConnected) return; if (xenfb->feature_update) { #ifdef XENFB_TYPE_REFRESH_PERIOD int period = 99999999; int idle = 1; if (xenfb_queue_full(xenfb)) return; for (l = xenfb->c.ds->listeners; l != NULL; l = l->next) { if (l->idle) continue; idle = 0; if (!l->gui_timer_interval) { if (period > GUI_REFRESH_INTERVAL) period = GUI_REFRESH_INTERVAL; } else { if (period > l->gui_timer_interval) period = l->gui_timer_interval; } } if (idle) 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 */ #endif } else { /* we don't get update notifications, thus use the * sledge hammer approach ... */ xenfb->up_fullscreen = 1; } /* resize if needed */ if (xenfb->do_resize) { xenfb->do_resize = 0; switch (xenfb->depth) { case 16: case 32: /* console.c supported depth -> buffer can be used directly */ qemu_free_displaysurface(xenfb->c.ds); xenfb->c.ds->surface = qemu_create_displaysurface_from (xenfb->width, xenfb->height, xenfb->depth, xenfb->row_stride, xenfb->pixels + xenfb->offset); break; default: /* we must convert stuff */ 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); xenfb->up_fullscreen = 1; } /* run queued updates */ if (xenfb->up_fullscreen) { xen_be_printf(&xenfb->c.xendev, 3, "update: fullscreen\n"); xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height); } else if (xenfb->up_count) { xen_be_printf(&xenfb->c.xendev, 3, "update: %d rects\n", xenfb->up_count); for (i = 0; i < xenfb->up_count; i++) xenfb_guest_copy(xenfb, xenfb->up_rects[i].x, xenfb->up_rects[i].y, xenfb->up_rects[i].w, xenfb->up_rects[i].h); } else { xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n"); } xenfb->up_count = 0; xenfb->up_fullscreen = 0; }
/* 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); }