summaryrefslogtreecommitdiffstats
path: root/ui/console.c
diff options
context:
space:
mode:
Diffstat (limited to 'ui/console.c')
-rw-r--r--ui/console.c104
1 files changed, 65 insertions, 39 deletions
diff --git a/ui/console.c b/ui/console.c
index 365a2c14b8..da434ce1b2 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -148,6 +148,8 @@ static DisplayState *get_alloc_displaystate(void);
static void text_console_update_cursor_timer(void);
static void text_console_update_cursor(void *opaque);
static bool displaychangelistener_has_dmabuf(DisplayChangeListener *dcl);
+static bool console_compatible_with(QemuConsole *con,
+ DisplayChangeListener *dcl, Error **errp);
static void gui_update(void *opaque)
{
@@ -1056,24 +1058,66 @@ static void console_putchar(QemuConsole *s, int ch)
}
}
+static void displaychangelistener_gfx_switch(DisplayChangeListener *dcl,
+ struct DisplaySurface *new_surface,
+ bool update)
+{
+ if (dcl->ops->dpy_gfx_switch) {
+ dcl->ops->dpy_gfx_switch(dcl, new_surface);
+ }
+
+ if (update && dcl->ops->dpy_gfx_update) {
+ dcl->ops->dpy_gfx_update(dcl, 0, 0,
+ surface_width(new_surface),
+ surface_height(new_surface));
+ }
+}
+
+static void dpy_gfx_create_texture(QemuConsole *con, DisplaySurface *surface)
+{
+ if (con->gl && con->gl->ops->dpy_gl_ctx_create_texture) {
+ con->gl->ops->dpy_gl_ctx_create_texture(con->gl, surface);
+ }
+}
+
+static void dpy_gfx_destroy_texture(QemuConsole *con, DisplaySurface *surface)
+{
+ if (con->gl && con->gl->ops->dpy_gl_ctx_destroy_texture) {
+ con->gl->ops->dpy_gl_ctx_destroy_texture(con->gl, surface);
+ }
+}
+
+static void dpy_gfx_update_texture(QemuConsole *con, DisplaySurface *surface,
+ int x, int y, int w, int h)
+{
+ if (con->gl && con->gl->ops->dpy_gl_ctx_update_texture) {
+ con->gl->ops->dpy_gl_ctx_update_texture(con->gl, surface, x, y, w, h);
+ }
+}
+
static void displaychangelistener_display_console(DisplayChangeListener *dcl,
- QemuConsole *con)
+ QemuConsole *con,
+ Error **errp)
{
static const char nodev[] =
"This VM has no graphic display device.";
static DisplaySurface *dummy;
- if (!con) {
- if (!dcl->ops->dpy_gfx_switch) {
- return;
- }
+ if (!con || !console_compatible_with(con, dcl, errp)) {
if (!dummy) {
dummy = qemu_create_placeholder_surface(640, 480, nodev);
}
- dcl->ops->dpy_gfx_switch(dcl, dummy);
+ if (con) {
+ dpy_gfx_create_texture(con, dummy);
+ }
+ displaychangelistener_gfx_switch(dcl, dummy, TRUE);
return;
}
+ dpy_gfx_create_texture(con, con->surface);
+ displaychangelistener_gfx_switch(dcl, con->surface,
+ con->scanout.kind == SCANOUT_SURFACE);
+
if (con->scanout.kind == SCANOUT_DMABUF &&
displaychangelistener_has_dmabuf(dcl)) {
dcl->ops->dpy_gl_scanout_dmabuf(dcl, con->scanout.dmabuf);
@@ -1088,14 +1132,7 @@ static void displaychangelistener_display_console(DisplayChangeListener *dcl,
con->scanout.texture.y,
con->scanout.texture.width,
con->scanout.texture.height);
- } else if (con->scanout.kind == SCANOUT_SURFACE &&
- dcl->ops->dpy_gfx_switch) {
- dcl->ops->dpy_gfx_switch(dcl, con->surface);
}
-
- dcl->ops->dpy_gfx_update(dcl, 0, 0,
- qemu_console_get_width(con, 0),
- qemu_console_get_height(con, 0));
}
void console_select(unsigned int index)
@@ -1114,7 +1151,7 @@ void console_select(unsigned int index)
if (dcl->con != NULL) {
continue;
}
- displaychangelistener_display_console(dcl, s);
+ displaychangelistener_display_console(dcl, s, NULL);
}
}
if (ds->have_text) {
@@ -1475,13 +1512,20 @@ static bool displaychangelistener_has_dmabuf(DisplayChangeListener *dcl)
return false;
}
-static bool dpy_compatible_with(QemuConsole *con,
- DisplayChangeListener *dcl, Error **errp)
+static bool console_compatible_with(QemuConsole *con,
+ DisplayChangeListener *dcl, Error **errp)
{
int flags;
flags = con->hw_ops->get_flags ? con->hw_ops->get_flags(con->hw) : 0;
+ if (console_has_gl(con) &&
+ !con->gl->ops->dpy_gl_ctx_is_compatible_dcl(con->gl, dcl)) {
+ error_setg(errp, "Display %s is incompatible with the GL context",
+ dcl->ops->dpy_name);
+ return false;
+ }
+
if (flags & GRAPHIC_FLAGS_GL &&
!console_has_gl(con)) {
error_setg(errp, "The console requires a GL context.");
@@ -1509,31 +1553,12 @@ void qemu_console_set_display_gl_ctx(QemuConsole *con, DisplayGLCtx *gl)
con->gl = gl;
}
-static bool dpy_gl_compatible_with(QemuConsole *con, DisplayChangeListener *dcl)
-{
- if (!con->gl) {
- return true;
- }
-
- return con->gl->ops->compatible_dcl == dcl->ops;
-}
-
void register_displaychangelistener(DisplayChangeListener *dcl)
{
QemuConsole *con;
assert(!dcl->ds);
- if (dcl->con && !dpy_gl_compatible_with(dcl->con, dcl)) {
- error_report("Display %s is incompatible with the GL context",
- dcl->ops->dpy_name);
- exit(1);
- }
-
- if (dcl->con) {
- dpy_compatible_with(dcl->con, dcl, &error_fatal);
- }
-
trace_displaychangelistener_register(dcl, dcl->ops->dpy_name);
dcl->ds = get_alloc_displaystate();
QLIST_INSERT_HEAD(&dcl->ds->listeners, dcl, next);
@@ -1544,7 +1569,7 @@ void register_displaychangelistener(DisplayChangeListener *dcl)
} else {
con = active_console;
}
- displaychangelistener_display_console(dcl, con);
+ displaychangelistener_display_console(dcl, con, dcl->con ? &error_fatal : NULL);
text_console_update_cursor(NULL);
}
@@ -1638,6 +1663,7 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
if (!qemu_console_is_visible(con)) {
return;
}
+ dpy_gfx_update_texture(con, con->surface, x, y, w, h);
QLIST_FOREACH(dcl, &s->listeners, next) {
if (con != (dcl->con ? dcl->con : active_console)) {
continue;
@@ -1682,14 +1708,14 @@ void dpy_gfx_replace_surface(QemuConsole *con,
con->scanout.kind = SCANOUT_SURFACE;
con->surface = surface;
+ dpy_gfx_create_texture(con, surface);
QLIST_FOREACH(dcl, &s->listeners, next) {
if (con != (dcl->con ? dcl->con : active_console)) {
continue;
}
- if (dcl->ops->dpy_gfx_switch) {
- dcl->ops->dpy_gfx_switch(dcl, surface);
- }
+ displaychangelistener_gfx_switch(dcl, surface, FALSE);
}
+ dpy_gfx_destroy_texture(con, old_surface);
qemu_free_displaysurface(old_surface);
}