return true;
}
-static void dpy_refresh(DisplayState *s)
+/*
+ * Safe DPY refresh for TCG guests. We use the exclusive mechanism to
+ * ensure the TCG vCPUs are quiescent so we can avoid races between
+ * dirty page tracking for direct frame-buffer access by the guest.
+ *
+ * This is a temporary stopgap until we've fixed the dirty tracking
+ * races in display adapters.
+ */
+static void do_safe_dpy_refresh(DisplayChangeListener *dcl)
{
- DisplayChangeListener *dcl;
-
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->ops->dpy_refresh) {
- dcl->ops->dpy_refresh(dcl);
- }
- }
+ qemu_mutex_unlock_iothread();
+ start_exclusive();
+ qemu_mutex_lock_iothread();
+ dcl->ops->dpy_refresh(dcl);
+ qemu_mutex_unlock_iothread();
+ end_exclusive();
+ qemu_mutex_lock_iothread();
}
-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
- int dst_x, int dst_y, int w, int h)
+static void dpy_refresh(DisplayState *s)
{
- DisplayState *s = con->ds;
DisplayChangeListener *dcl;
- if (!qemu_console_is_visible(con)) {
- return;
- }
QLIST_FOREACH(dcl, &s->listeners, next) {
- if (con != (dcl->con ? dcl->con : active_console)) {
- continue;
- }
- if (dcl->ops->dpy_gfx_copy) {
- dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
- } else { /* TODO */
- dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
+ if (dcl->ops->dpy_refresh) {
+ if (tcg_enabled()) {
+ do_safe_dpy_refresh(dcl);
+ } else {
+ dcl->ops->dpy_refresh(dcl);
+ }
}
}
}
return con->gl->ops->dpy_gl_ctx_get_current(con->gl);
}
-void dpy_gl_scanout(QemuConsole *con,
- uint32_t backing_id, bool backing_y_0_top,
- uint32_t backing_width, uint32_t backing_height,
- uint32_t x, uint32_t y, uint32_t width, uint32_t height)
+void dpy_gl_scanout_disable(QemuConsole *con)
{
assert(con->gl);
- con->gl->ops->dpy_gl_scanout(con->gl, backing_id,
- backing_y_0_top,
- backing_width, backing_height,
- x, y, width, height);
+ if (con->gl->ops->dpy_gl_scanout_disable) {
+ con->gl->ops->dpy_gl_scanout_disable(con->gl);
+ } else {
+ con->gl->ops->dpy_gl_scanout_texture(con->gl, 0, false, 0, 0,
+ 0, 0, 0, 0);
+ }
+}
+
+void dpy_gl_scanout_texture(QemuConsole *con,
+ uint32_t backing_id,
+ bool backing_y_0_top,
+ uint32_t backing_width,
+ uint32_t backing_height,
+ uint32_t x, uint32_t y,
+ uint32_t width, uint32_t height)
+{
+ assert(con->gl);
+ con->gl->ops->dpy_gl_scanout_texture(con->gl, backing_id,
+ backing_y_0_top,
+ backing_width, backing_height,
+ x, y, width, height);
}
void dpy_gl_update(QemuConsole *con,
assert(s->console_type == GRAPHIC_CONSOLE);
- if (s->surface &&
+ if (s->surface && (s->surface->flags & QEMU_ALLOCATED_FLAG) &&
pixman_image_get_width(s->surface->image) == width &&
pixman_image_get_height(s->surface->image) == height) {
return;
dpy_gfx_replace_surface(s, surface);
}
-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
- int dst_x, int dst_y, int w, int h)
-{
- assert(con->console_type == GRAPHIC_CONSOLE);
- dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
-}
-
DisplaySurface *qemu_console_surface(QemuConsole *console)
{
return console->surface;
int val;
ChardevVC *vc;
+ backend->type = CHARDEV_BACKEND_KIND_VC;
vc = backend->u.vc.data = g_new0(ChardevVC, 1);
qemu_chr_parse_common(opts, qapi_ChardevVC_base(vc));
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_VC;
cc->parse = qemu_chr_parse_vc;
cc->open = vc_chr_open;
cc->chr_write = vc_chr_write;