Example #1
0
File: xenfb.c Project: Epeius/qemu
/*
 * 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;
}
Example #2
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);
}
Example #3
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;
	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;
}
Example #5
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);
}