diff --git a/audio/audio_int.h b/audio/audio_int.h index d51d63f08d..e57ff50155 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -143,7 +143,7 @@ struct audio_driver { void *(*init) (Audiodev *); void (*fini) (void *); #ifdef CONFIG_GIO - void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager); + void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p); #endif struct audio_pcm_ops *pcm_ops; int can_be_default; diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index 722df0355e..fece74f78c 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -43,6 +43,7 @@ typedef struct DBusAudio { GDBusObjectManagerServer *server; + bool p2p; GDBusObjectSkeleton *audio; QemuDBusDisplay1Audio *iface; GHashTable *out_listeners; @@ -448,7 +449,8 @@ dbus_audio_register_listener(AudioState *s, bool out) { DBusAudio *da = s->drv_opaque; - const char *sender = g_dbus_method_invocation_get_sender(invocation); + const char *sender = + da->p2p ? "p2p" : g_dbus_method_invocation_get_sender(invocation); g_autoptr(GDBusConnection) listener_conn = NULL; g_autoptr(GError) err = NULL; g_autoptr(GSocket) socket = NULL; @@ -591,7 +593,7 @@ dbus_audio_register_in_listener(AudioState *s, } static void -dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server) +dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p) { DBusAudio *da = s->drv_opaque; @@ -599,6 +601,7 @@ dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server) g_assert(!da->server); da->server = g_object_ref(server); + da->p2p = p2p; da->audio = g_dbus_object_skeleton_new(DBUS_DISPLAY1_AUDIO_PATH); da->iface = qemu_dbus_display1_audio_skeleton_new(); diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c index fcfd40c3ac..ec99ec887a 100644 --- a/hw/display/qxl-render.c +++ b/hw/display/qxl-render.c @@ -290,7 +290,7 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor, return c; fail: - cursor_put(c); + cursor_unref(c); return NULL; } @@ -336,7 +336,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) } qemu_mutex_lock(&qxl->ssd.lock); if (qxl->ssd.cursor) { - cursor_put(qxl->ssd.cursor); + cursor_unref(qxl->ssd.cursor); } qxl->ssd.cursor = c; qxl->ssd.mouse_x = cmd->u.set.position.x; diff --git a/hw/display/qxl.c b/hw/display/qxl.c index ec712d3ca2..80ce1e9a93 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -299,7 +299,7 @@ void qxl_spice_reset_cursor(PCIQXLDevice *qxl) qxl->guest_cursor = 0; qemu_mutex_unlock(&qxl->track_lock); if (qxl->ssd.cursor) { - cursor_put(qxl->ssd.cursor); + cursor_unref(qxl->ssd.cursor); } qxl->ssd.cursor = cursor_builtin_hidden(); } diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 59ae7f74b8..09591fbd39 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -550,12 +550,12 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s, default: fprintf(stderr, "%s: unhandled bpp %d, using fallback cursor\n", __func__, c->bpp); - cursor_put(qc); + cursor_unref(qc); qc = cursor_builtin_left_ptr(); } dpy_cursor_define(s->vga.con, qc); - cursor_put(qc); + cursor_unref(qc); } #endif diff --git a/include/ui/console.h b/include/ui/console.h index 1cb53acc33..2a8fab091f 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -151,8 +151,8 @@ typedef struct QEMUCursor { } QEMUCursor; QEMUCursor *cursor_alloc(int width, int height); -void cursor_get(QEMUCursor *c); -void cursor_put(QEMUCursor *c); +QEMUCursor *cursor_ref(QEMUCursor *c); +void cursor_unref(QEMUCursor *c); QEMUCursor *cursor_builtin_hidden(void); QEMUCursor *cursor_builtin_left_ptr(void); void cursor_print_ascii_art(QEMUCursor *c, const char *prefix); @@ -459,6 +459,7 @@ QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head); QemuConsole *qemu_console_lookup_by_device_name(const char *device_id, uint32_t head, Error **errp); QemuConsole *qemu_console_lookup_unused(void); +QEMUCursor *qemu_console_get_cursor(QemuConsole *con); bool qemu_console_is_visible(QemuConsole *con); bool qemu_console_is_graphic(QemuConsole *con); bool qemu_console_is_fixedsize(QemuConsole *con); diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index 2fb6e0dd6b..53d953ddf4 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -22,6 +22,8 @@ typedef struct egl_fb { QemuDmaBuf *dmabuf; } egl_fb; +#define EGL_FB_INIT { 0, } + void egl_fb_destroy(egl_fb *fb); void egl_fb_setup_default(egl_fb *fb, int width, int height); void egl_fb_setup_for_tex(egl_fb *fb, int width, int height, @@ -63,4 +65,6 @@ int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, DisplayGLMode mode); EGLContext qemu_egl_init_ctx(void); bool qemu_egl_has_dmabuf(void); +bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp); + #endif /* EGL_HELPERS_H */ diff --git a/meson.build b/meson.build index 6bcab8bf0d..29f8644d6d 100644 --- a/meson.build +++ b/meson.build @@ -1746,8 +1746,8 @@ dbus_display = get_option('dbus_display') \ error_message: '-display dbus requires glib>=2.64') \ .require(gdbus_codegen.found(), error_message: gdbus_codegen_error.format('-display dbus')) \ - .require(opengl.found() and gbm.found(), - error_message: '-display dbus requires epoxy/egl and gbm') \ + .require(targetos != 'windows', + error_message: '-display dbus is not available on Windows') \ .allowed() have_virtfs = get_option('virtfs') \ diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index c9292b64fb..85ea4e8d99 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -101,7 +101,7 @@ qtests_i386 = \ 'numa-test' ] -if dbus_display +if dbus_display and targetos != 'windows' qtests_i386 += ['dbus-display-test'] endif diff --git a/ui/console.c b/ui/console.c index 98b701f5a3..f3783021e5 100644 --- a/ui/console.c +++ b/ui/console.c @@ -94,6 +94,8 @@ struct QemuConsole { uint32_t head; QemuUIInfo ui_info; QEMUTimer *ui_timer; + QEMUCursor *cursor; + int cursor_x, cursor_y, cursor_on; const GraphicHwOps *hw_ops; void *hw; @@ -1661,6 +1663,12 @@ void register_displaychangelistener(DisplayChangeListener *dcl) con = active_console; } displaychangelistener_display_console(dcl, con, dcl->con ? &error_fatal : NULL); + if (con && con->cursor && dcl->ops->dpy_cursor_define) { + dcl->ops->dpy_cursor_define(dcl, con->cursor); + } + if (con && dcl->ops->dpy_mouse_set) { + dcl->ops->dpy_mouse_set(dcl, con->cursor_x, con->cursor_y, con->cursor_on); + } text_console_update_cursor(NULL); } @@ -1905,6 +1913,9 @@ void dpy_mouse_set(QemuConsole *con, int x, int y, int on) DisplayState *s = con->ds; DisplayChangeListener *dcl; + con->cursor_x = x; + con->cursor_y = y; + con->cursor_on = on; if (!qemu_console_is_visible(con)) { return; } @@ -1923,6 +1934,8 @@ void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor) DisplayState *s = con->ds; DisplayChangeListener *dcl; + cursor_unref(con->cursor); + con->cursor = cursor_ref(cursor); if (!qemu_console_is_visible(con)) { return; } @@ -2288,6 +2301,11 @@ QemuConsole *qemu_console_lookup_unused(void) return NULL; } +QEMUCursor *qemu_console_get_cursor(QemuConsole *con) +{ + return con->cursor; +} + bool qemu_console_is_visible(QemuConsole *con) { return (con == active_console) || (con->dcls > 0); diff --git a/ui/cursor.c b/ui/cursor.c index 835f0802f9..6fe67990e2 100644 --- a/ui/cursor.c +++ b/ui/cursor.c @@ -106,12 +106,13 @@ QEMUCursor *cursor_alloc(int width, int height) return c; } -void cursor_get(QEMUCursor *c) +QEMUCursor *cursor_ref(QEMUCursor *c) { c->refcount++; + return c; } -void cursor_put(QEMUCursor *c) +void cursor_unref(QEMUCursor *c) { if (c == NULL) return; diff --git a/ui/dbus-clipboard.c b/ui/dbus-clipboard.c index df9a754a8d..fe7fcdecb6 100644 --- a/ui/dbus-clipboard.c +++ b/ui/dbus-clipboard.c @@ -204,15 +204,6 @@ dbus_clipboard_unregister_proxy(DBusDisplay *dpy) g_clear_object(&dpy->clipboard_proxy); } -static void -dbus_on_clipboard_proxy_name_owner_changed( - DBusDisplay *dpy, - GObject *object, - GParamSpec *pspec) -{ - dbus_clipboard_unregister_proxy(dpy); -} - static gboolean dbus_clipboard_register( DBusDisplay *dpy, @@ -220,6 +211,7 @@ dbus_clipboard_register( { g_autoptr(GError) err = NULL; const char *name = NULL; + GDBusConnection *connection = g_dbus_method_invocation_get_connection(invocation); if (dpy->clipboard_proxy) { g_dbus_method_invocation_return_error( @@ -232,7 +224,7 @@ dbus_clipboard_register( dpy->clipboard_proxy = qemu_dbus_display1_clipboard_proxy_new_sync( - g_dbus_method_invocation_get_connection(invocation), + connection, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, g_dbus_method_invocation_get_sender(invocation), "/org/qemu/Display1/Clipboard", @@ -252,7 +244,11 @@ dbus_clipboard_register( g_object_connect(dpy->clipboard_proxy, "swapped-signal::notify::g-name-owner", - dbus_on_clipboard_proxy_name_owner_changed, dpy, + dbus_clipboard_unregister_proxy, dpy, + NULL); + g_object_connect(connection, + "swapped-signal::closed", + dbus_clipboard_unregister_proxy, dpy, NULL); qemu_clipboard_reset_serial(); diff --git a/ui/dbus-console.c b/ui/dbus-console.c index 0bfaa2298d..f77bc49d2e 100644 --- a/ui/dbus-console.c +++ b/ui/dbus-console.c @@ -411,15 +411,21 @@ dbus_mouse_release(DBusDisplayConsole *ddc, return DBUS_METHOD_INVOCATION_HANDLED; } +static void +dbus_mouse_update_is_absolute(DBusDisplayConsole *ddc) +{ + g_object_set(ddc->iface_mouse, + "is-absolute", qemu_input_is_absolute(), + NULL); +} + static void dbus_mouse_mode_change(Notifier *notify, void *data) { DBusDisplayConsole *ddc = container_of(notify, DBusDisplayConsole, mouse_mode_notifier); - g_object_set(ddc->iface_mouse, - "is-absolute", qemu_input_is_absolute(), - NULL); + dbus_mouse_update_is_absolute(ddc); } int dbus_display_console_get_index(DBusDisplayConsole *ddc) @@ -492,6 +498,7 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con) register_displaychangelistener(&ddc->dcl); ddc->mouse_mode_notifier.notify = dbus_mouse_mode_change; qemu_add_mouse_mode_change_notifier(&ddc->mouse_mode_notifier); + dbus_mouse_update_is_absolute(ddc); return ddc; } diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c index 57d4e401db..911acdc529 100644 --- a/ui/dbus-listener.c +++ b/ui/dbus-listener.c @@ -27,9 +27,11 @@ #include "dbus.h" #include +#ifdef CONFIG_OPENGL #include "ui/shader.h" #include "ui/egl-helpers.h" #include "ui/egl-context.h" +#endif #include "trace.h" struct _DBusDisplayListener { @@ -48,6 +50,7 @@ struct _DBusDisplayListener { G_DEFINE_TYPE(DBusDisplayListener, dbus_display_listener, G_TYPE_OBJECT) +#ifdef CONFIG_GBM static void dbus_update_gl_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) @@ -149,7 +152,7 @@ static void dbus_cursor_dmabuf(DisplayChangeListener *dcl, DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); DisplaySurface *ds; GVariant *v_data = NULL; - egl_fb cursor_fb; + egl_fb cursor_fb = EGL_FB_INIT; if (!dmabuf) { qemu_dbus_display1_listener_call_mouse_set( @@ -229,12 +232,14 @@ static void dbus_gl_refresh(DisplayChangeListener *dcl) ddl->gl_updates = 0; } } +#endif static void dbus_refresh(DisplayChangeListener *dcl) { graphic_hw_update(dcl->con); } +#ifdef CONFIG_GBM static void dbus_gl_gfx_update(DisplayChangeListener *dcl, int x, int y, int w, int h) { @@ -242,6 +247,7 @@ static void dbus_gl_gfx_update(DisplayChangeListener *dcl, ddl->gl_updates++; } +#endif static void dbus_gfx_update(DisplayChangeListener *dcl, int x, int y, int w, int h) @@ -296,6 +302,7 @@ static void dbus_gfx_update(DisplayChangeListener *dcl, DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL); } +#ifdef CONFIG_GBM static void dbus_gl_gfx_switch(DisplayChangeListener *dcl, struct DisplaySurface *new_surface) { @@ -311,6 +318,7 @@ static void dbus_gl_gfx_switch(DisplayChangeListener *dcl, width, height, 0, 0, width, height); } } +#endif static void dbus_gfx_switch(DisplayChangeListener *dcl, struct DisplaySurface *new_surface) @@ -339,14 +347,13 @@ static void dbus_cursor_define(DisplayChangeListener *dcl, DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); GVariant *v_data = NULL; - cursor_get(c); v_data = g_variant_new_from_data( G_VARIANT_TYPE("ay"), c->data, c->width * c->height * 4, TRUE, - (GDestroyNotify)cursor_put, - c); + (GDestroyNotify)cursor_unref, + cursor_ref(c)); qemu_dbus_display1_listener_call_cursor_define( ddl->proxy, @@ -362,6 +369,7 @@ static void dbus_cursor_define(DisplayChangeListener *dcl, NULL); } +#ifdef CONFIG_GBM const DisplayChangeListenerOps dbus_gl_dcl_ops = { .dpy_name = "dbus-gl", .dpy_gfx_update = dbus_gl_gfx_update, @@ -379,6 +387,7 @@ const DisplayChangeListenerOps dbus_gl_dcl_ops = { .dpy_gl_release_dmabuf = dbus_release_dmabuf, .dpy_gl_update = dbus_scanout_update, }; +#endif const DisplayChangeListenerOps dbus_dcl_ops = { .dpy_name = "dbus", @@ -407,11 +416,12 @@ dbus_display_listener_constructed(GObject *object) { DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object); + ddl->dcl.ops = &dbus_dcl_ops; +#ifdef CONFIG_GBM if (display_opengl) { ddl->dcl.ops = &dbus_gl_dcl_ops; - } else { - ddl->dcl.ops = &dbus_dcl_ops; } +#endif G_OBJECT_CLASS(dbus_display_listener_parent_class)->constructed(object); } diff --git a/ui/dbus.c b/ui/dbus.c index f2dcba03d0..0513de9918 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -30,8 +30,10 @@ #include "qom/object_interfaces.h" #include "sysemu/sysemu.h" #include "ui/dbus-module.h" +#ifdef CONFIG_OPENGL #include "ui/egl-helpers.h" #include "ui/egl-context.h" +#endif #include "audio/audio.h" #include "audio/audio_int.h" #include "qapi/error.h" @@ -41,11 +43,14 @@ static DBusDisplay *dbus_display; +#ifdef CONFIG_OPENGL static QEMUGLContext dbus_create_context(DisplayGLCtx *dgc, QEMUGLParams *params) { +#ifdef CONFIG_GBM eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, qemu_egl_rn_ctx); +#endif return qemu_egl_create_context(dgc, params); } @@ -53,7 +58,11 @@ static bool dbus_is_compatible_dcl(DisplayGLCtx *dgc, DisplayChangeListener *dcl) { - return dcl->ops == &dbus_gl_dcl_ops || dcl->ops == &dbus_console_dcl_ops; + return +#ifdef CONFIG_GBM + dcl->ops == &dbus_gl_dcl_ops || +#endif + dcl->ops == &dbus_console_dcl_ops; } static void @@ -84,6 +93,7 @@ static const DisplayGLCtxOps dbus_gl_ops = { .dpy_gl_ctx_destroy_texture = dbus_destroy_texture, .dpy_gl_ctx_update_texture = dbus_update_texture, }; +#endif static NotifierList dbus_display_notifiers = NOTIFIER_LIST_INITIALIZER(dbus_display_notifiers); @@ -112,10 +122,12 @@ dbus_display_init(Object *o) DBusDisplay *dd = DBUS_DISPLAY(o); g_autoptr(GDBusObjectSkeleton) vm = NULL; +#ifdef CONFIG_OPENGL dd->glctx.ops = &dbus_gl_ops; if (display_opengl) { dd->glctx.gls = qemu_gl_init_shader(); } +#endif dd->iface = qemu_dbus_display1_vm_skeleton_new(); dd->consoles = g_ptr_array_new_with_free_func(g_object_unref); @@ -152,7 +164,9 @@ dbus_display_finalize(Object *o) g_clear_object(&dd->iface); g_free(dd->dbus_addr); g_free(dd->audiodev); +#ifdef CONFIG_OPENGL g_clear_pointer(&dd->glctx.gls, qemu_gl_fini_shader); +#endif dbus_display = NULL; } @@ -220,7 +234,7 @@ dbus_display_complete(UserCreatable *uc, Error **errp) dd->audiodev); return; } - audio_state->drv->set_dbus_server(audio_state, dd->server); + audio_state->drv->set_dbus_server(audio_state, dd->server, dd->p2p); } consoles = g_array_new(FALSE, FALSE, sizeof(guint32)); @@ -451,12 +465,11 @@ early_dbus_init(DisplayOptions *opts) DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_OFF; if (mode != DISPLAYGL_MODE_OFF) { - if (egl_rendernode_init(opts->u.dbus.rendernode, mode) < 0) { - error_report("dbus: render node init failed"); - exit(1); - } - - display_opengl = 1; +#ifdef CONFIG_OPENGL + egl_init(opts->u.dbus.rendernode, mode, &error_fatal); +#else + error_report("dbus: GL rendering is not supported"); +#endif } type_register(&dbus_vc_type_info); diff --git a/ui/egl-headless.c b/ui/egl-headless.c index ae07e91302..ef70e6a18e 100644 --- a/ui/egl-headless.c +++ b/ui/egl-headless.c @@ -1,7 +1,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "qemu/module.h" -#include "sysemu/sysemu.h" +#include "qapi/error.h" #include "ui/console.h" #include "ui/egl-helpers.h" #include "ui/egl-context.h" @@ -191,21 +191,21 @@ static const DisplayGLCtxOps eglctx_ops = { static void early_egl_headless_init(DisplayOptions *opts) { - display_opengl = 1; + DisplayGLMode mode = DISPLAYGL_MODE_ON; + + if (opts->has_gl) { + mode = opts->gl; + } + + egl_init(opts->u.egl_headless.rendernode, mode, &error_fatal); } static void egl_headless_init(DisplayState *ds, DisplayOptions *opts) { - DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_ON; QemuConsole *con; egl_dpy *edpy; int idx; - if (egl_rendernode_init(opts->u.egl_headless.rendernode, mode) < 0) { - error_report("egl: render node init failed"); - exit(1); - } - for (idx = 0;; idx++) { DisplayGLCtx *ctx; diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3a88245b67..4203163ace 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -19,6 +19,8 @@ #include "qemu/error-report.h" #include "ui/console.h" #include "ui/egl-helpers.h" +#include "sysemu/sysemu.h" +#include "qapi/error.h" EGLDisplay *qemu_egl_display; EGLConfig qemu_egl_config; @@ -26,6 +28,48 @@ DisplayGLMode qemu_egl_mode; /* ------------------------------------------------------------------ */ +#if defined(CONFIG_X11) || defined(CONFIG_GBM) +static const char *egl_get_error_string(void) +{ + EGLint error = eglGetError(); + + switch (error) { + case EGL_SUCCESS: + return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT"; + case EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG"; + case EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY"; + case EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE"; + case EGL_BAD_MATCH: + return "EGL_BAD_MATCH"; + case EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER"; + case EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW"; + case EGL_CONTEXT_LOST: + return "EGL_CONTEXT_LOST"; + default: + return "Unknown EGL error"; + } +} +#endif + static void egl_fb_delete_texture(egl_fb *fb) { if (!fb->delete_texture) { @@ -438,20 +482,20 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, qemu_egl_display = qemu_egl_get_display(dpy, platform); if (qemu_egl_display == EGL_NO_DISPLAY) { - error_report("egl: eglGetDisplay failed"); + error_report("egl: eglGetDisplay failed: %s", egl_get_error_string()); return -1; } b = eglInitialize(qemu_egl_display, &major, &minor); if (b == EGL_FALSE) { - error_report("egl: eglInitialize failed"); + error_report("egl: eglInitialize failed: %s", egl_get_error_string()); return -1; } b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API); if (b == EGL_FALSE) { - error_report("egl: eglBindAPI failed (%s mode)", - gles ? "gles" : "core"); + error_report("egl: eglBindAPI failed (%s mode): %s", + gles ? "gles" : "core", egl_get_error_string()); return -1; } @@ -459,8 +503,8 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, gles ? conf_att_gles : conf_att_core, &qemu_egl_config, 1, &n); if (b == EGL_FALSE || n != 1) { - error_report("egl: eglChooseConfig failed (%s mode)", - gles ? "gles" : "core"); + error_report("egl: eglChooseConfig failed (%s mode): %s", + gles ? "gles" : "core", egl_get_error_string()); return -1; } @@ -527,3 +571,25 @@ EGLContext qemu_egl_init_ctx(void) return ectx; } + +bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp) +{ + ERRP_GUARD(); + + if (mode == DISPLAYGL_MODE_OFF) { + error_setg(errp, "egl: turning off GL doesn't make sense"); + return false; + } + +#ifdef CONFIG_GBM + if (egl_rendernode_init(rendernode, mode) < 0) { + error_setg(errp, "egl: render node init failed"); + return false; + } + display_opengl = 1; + return true; +#else + error_setg(errp, "egl: not available on this platform"); + return false; +#endif +} diff --git a/ui/meson.build b/ui/meson.build index 612ea2325b..330369707d 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -83,7 +83,9 @@ if dbus_display '--interface-prefix', 'org.qemu.', '--c-namespace', 'QemuDBus', '--generate-c-code', '@BASENAME@']) - dbus_ss.add(when: [gio, pixman, opengl, gbm], + dbus_display1_lib = static_library('dbus-display1', dbus_display1, dependencies: gio) + dbus_display1_dep = declare_dependency(link_with: dbus_display1_lib, include_directories: include_directories('.')) + dbus_ss.add(when: [gio, pixman, dbus_display1_dep], if_true: [files( 'dbus-chardev.c', 'dbus-clipboard.c', @@ -91,7 +93,7 @@ if dbus_display 'dbus-error.c', 'dbus-listener.c', 'dbus.c', - ), dbus_display1]) + ), opengl, gbm]) ui_modules += {'dbus' : dbus_ss} endif diff --git a/ui/sdl2.c b/ui/sdl2.c index 8cb77416af..35c58c1104 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -58,6 +58,11 @@ static Notifier mouse_mode_notifier; #define SDL2_MAX_IDLE_COUNT (2 * GUI_REFRESH_INTERVAL_DEFAULT \ / SDL2_REFRESH_INTERVAL_BUSY + 1) +/* introduced in SDL 2.0.10 */ +#ifndef SDL_HINT_RENDER_BATCHING +#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING" +#endif + static void sdl_update_caption(struct sdl2_console *scon); static struct sdl2_console *get_scon_from_window(uint32_t window_id) @@ -99,9 +104,20 @@ void sdl2_window_create(struct sdl2_console *scon) surface_width(scon->surface), surface_height(scon->surface), flags); - scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0); if (scon->opengl) { - scon->winctx = SDL_GL_GetCurrentContext(); + const char *driver = "opengl"; + + if (scon->opts->gl == DISPLAYGL_MODE_ES) { + driver = "opengles2"; + } + + SDL_SetHint(SDL_HINT_RENDER_DRIVER, driver); + SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1"); + } + scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0); + + if (scon->opengl) { + scon->winctx = SDL_GL_CreateContext(scon->real_window); } sdl_update_caption(scon); } @@ -112,6 +128,8 @@ void sdl2_window_destroy(struct sdl2_console *scon) return; } + SDL_GL_DeleteContext(scon->winctx); + scon->winctx = NULL; SDL_DestroyRenderer(scon->real_renderer); scon->real_renderer = NULL; SDL_DestroyWindow(scon->real_window); @@ -841,6 +859,10 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) } #endif + if (SDL_GetHintBoolean("QEMU_ENABLE_SDL_LOGGING", SDL_FALSE)) { + SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE); + } + if (SDL_Init(SDL_INIT_VIDEO)) { fprintf(stderr, "Could not initialize SDL(%s) - exiting\n", SDL_GetError()); diff --git a/ui/shader/texture-blit-flip.vert b/ui/shader/texture-blit-flip.vert index ba081fa5a6..f7a448d229 100644 --- a/ui/shader/texture-blit-flip.vert +++ b/ui/shader/texture-blit-flip.vert @@ -1,4 +1,3 @@ - #version 300 es in vec2 in_position; diff --git a/ui/shader/texture-blit.frag b/ui/shader/texture-blit.frag index bfa202c22b..8ed95a46b6 100644 --- a/ui/shader/texture-blit.frag +++ b/ui/shader/texture-blit.frag @@ -1,4 +1,3 @@ - #version 300 es uniform sampler2D image; diff --git a/ui/shader/texture-blit.vert b/ui/shader/texture-blit.vert index 6fe2744d68..fb48d70665 100644 --- a/ui/shader/texture-blit.vert +++ b/ui/shader/texture-blit.vert @@ -1,4 +1,3 @@ - #version 300 es in vec2 in_position; diff --git a/ui/spice-core.c b/ui/spice-core.c index 76f7c2bc3d..b05c830086 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -820,12 +820,7 @@ static void qemu_spice_init(void) "incompatible with -spice port/tls-port"); exit(1); } - if (egl_rendernode_init(qemu_opt_get(opts, "rendernode"), - DISPLAYGL_MODE_ON) != 0) { - error_report("Failed to initialize EGL render node for SPICE GL"); - exit(1); - } - display_opengl = 1; + egl_init(qemu_opt_get(opts, "rendernode"), DISPLAYGL_MODE_ON, &error_fatal); spice_opengl = 1; } #endif diff --git a/ui/spice-display.c b/ui/spice-display.c index 16802f99cb..5bee19a7f9 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -460,11 +460,11 @@ void qemu_spice_cursor_refresh_bh(void *opaque) if (ssd->cursor) { QEMUCursor *c = ssd->cursor; assert(ssd->dcl.con); - cursor_get(c); + cursor_ref(c); qemu_mutex_unlock(&ssd->lock); dpy_cursor_define(ssd->dcl.con, c); qemu_mutex_lock(&ssd->lock); - cursor_put(c); + cursor_unref(c); } if (ssd->mouse_x != -1 && ssd->mouse_y != -1) { @@ -765,8 +765,8 @@ static void display_mouse_define(DisplayChangeListener *dcl, SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); qemu_mutex_lock(&ssd->lock); - cursor_get(c); - cursor_put(ssd->cursor); + cursor_ref(c); + cursor_unref(ssd->cursor); ssd->cursor = c; ssd->hot_x = c->hot_x; ssd->hot_y = c->hot_y; diff --git a/ui/vnc.c b/ui/vnc.c index d9eacad759..bbd8b6baae 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -988,10 +988,10 @@ static void vnc_mouse_set(DisplayChangeListener *dcl, static int vnc_cursor_define(VncState *vs) { - QEMUCursor *c = vs->vd->cursor; + QEMUCursor *c = qemu_console_get_cursor(vs->vd->dcl.con); int isize; - if (!vs->vd->cursor) { + if (!c) { return -1; } @@ -1029,11 +1029,7 @@ static void vnc_dpy_cursor_define(DisplayChangeListener *dcl, VncDisplay *vd = container_of(dcl, VncDisplay, dcl); VncState *vs; - cursor_put(vd->cursor); g_free(vd->cursor_mask); - - vd->cursor = c; - cursor_get(vd->cursor); vd->cursor_msize = cursor_get_mono_bpl(c) * c->height; vd->cursor_mask = g_malloc0(vd->cursor_msize); cursor_get_mono_mask(c, 0, vd->cursor_mask); diff --git a/ui/vnc.h b/ui/vnc.h index a60fb13115..757fa83044 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -159,7 +159,6 @@ struct VncDisplay QKbdState *kbd; QemuMutex mutex; - QEMUCursor *cursor; int cursor_msize; uint8_t *cursor_mask;