ui: dbus & misc fixes

v2:
 - fix crash spotted by avocado VNC test
 -----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmQPgRIcHG1hcmNhbmRy
 ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5QDFEACef6cbSlTtQji1hV+x
 FM2ESPn0tgg9YVmtjsC1zqcdOEKsbs+2SQxBSs6tvQGwX5CgtnmyEsH5/Y4+TU64
 r6dvGAhokEkhiyHwnC+DFw0ajYAaDK96RfJ02tPQ58lrBTyioKZH9K/3mB6pMFEG
 aroE1Z3SQqqMnP+zsQ64nYuJrTXnv9iFejIxnuou+LyXdxmwLWAl5e47eZYaTmrh
 RrJYbCyHbiL5bx6mOmAL1XlO9jJD4o0FrqRWFn4zz1T+w4FvUC/uX52XwRn1G/Hk
 oHNnJBt95czCQ3S43xX0VTVrT9vLAptQzQc45KfegRL3XqPLgTgn4eocBQCYLmHZ
 jKnUsE9VjBNCbkIzgfN9RP/zEklD/3lAHzrW5US7q7oTTYksyxN+pmvfrYbUvKWP
 Oq/EQtpv66R06hjpxD76ime4+Y8WN7I3F/fJS8jl2QDy5I/2IzFSIOD9Rt5PGbky
 xsIdr7QPzlN4ZKpnsRCNeEPwcR/kiv4grIF7jBAxxz3k5UENtIVSJkHBEEQjMy8O
 +ZCvnHsbjPGxFtnlNTvtGsR2hiKYRCJSG/C4YQryTDWoScomlF6UWxzbapjs9CRW
 /GR+98Z2QfwOtRRRteRRt9UFdC/T0DquxnRyJxa5N4VxMiWzmhtCOzmn4oc1THbG
 5UqDhRNSWEJn9iIvKca5ahSWLw==
 =Rjcs
 -----END PGP SIGNATURE-----

Merge tag 'display-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging

ui: dbus & misc fixes

v2:
- fix crash spotted by avocado VNC test

# -----BEGIN PGP SIGNATURE-----
#
# iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmQPgRIcHG1hcmNhbmRy
# ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5QDFEACef6cbSlTtQji1hV+x
# FM2ESPn0tgg9YVmtjsC1zqcdOEKsbs+2SQxBSs6tvQGwX5CgtnmyEsH5/Y4+TU64
# r6dvGAhokEkhiyHwnC+DFw0ajYAaDK96RfJ02tPQ58lrBTyioKZH9K/3mB6pMFEG
# aroE1Z3SQqqMnP+zsQ64nYuJrTXnv9iFejIxnuou+LyXdxmwLWAl5e47eZYaTmrh
# RrJYbCyHbiL5bx6mOmAL1XlO9jJD4o0FrqRWFn4zz1T+w4FvUC/uX52XwRn1G/Hk
# oHNnJBt95czCQ3S43xX0VTVrT9vLAptQzQc45KfegRL3XqPLgTgn4eocBQCYLmHZ
# jKnUsE9VjBNCbkIzgfN9RP/zEklD/3lAHzrW5US7q7oTTYksyxN+pmvfrYbUvKWP
# Oq/EQtpv66R06hjpxD76ime4+Y8WN7I3F/fJS8jl2QDy5I/2IzFSIOD9Rt5PGbky
# xsIdr7QPzlN4ZKpnsRCNeEPwcR/kiv4grIF7jBAxxz3k5UENtIVSJkHBEEQjMy8O
# +ZCvnHsbjPGxFtnlNTvtGsR2hiKYRCJSG/C4YQryTDWoScomlF6UWxzbapjs9CRW
# /GR+98Z2QfwOtRRRteRRt9UFdC/T0DquxnRyJxa5N4VxMiWzmhtCOzmn4oc1THbG
# 5UqDhRNSWEJn9iIvKca5ahSWLw==
# =Rjcs
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 13 Mar 2023 20:01:22 GMT
# gpg:                using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg:                issuer "marcandre.lureau@redhat.com"
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full]
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* tag 'display-pull-request' of https://gitlab.com/marcandre.lureau/qemu:
  ui/dbus: restrict opengl to gbm-enabled config
  ui/dbus: do not require opengl & gbm
  ui: introduce egl_init()
  ui/sdl: try to instantiate the matching opengl renderer
  ui/sdl: add QEMU_ENABLE_SDL_LOGGING setting/environment
  ui/egl: print EGL error, helping debugging
  ui/shader: fix #version directive must occur on first line
  ui/sdl: get the GL context from the window
  ui: set cursor position upon listener registration
  ui: set cursor upon listener registration
  ui: keep current cursor with QemuConsole
  ui: rename cursor_{get->ref}, return it
  ui: rename cursor_{put->unref}
  meson: ensure dbus-display generated code is built before other units
  ui/dbus: set mouse is-absolute during console creation
  audio/dbus: there are no sender for p2p mode
  ui/dbus: unregister clipboard on connection close
  ui/dbus: initialize cursor_fb

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2023-03-14 14:28:58 +00:00
commit 7c3cc428c7
26 changed files with 211 additions and 81 deletions

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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();
}

View file

@ -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

View file

@ -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);

View file

@ -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 */

View file

@ -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') \

View file

@ -101,7 +101,7 @@ qtests_i386 = \
'numa-test'
]
if dbus_display
if dbus_display and targetos != 'windows'
qtests_i386 += ['dbus-display-test']
endif

View file

@ -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);

View file

@ -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;

View file

@ -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();

View file

@ -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;
}

View file

@ -27,9 +27,11 @@
#include "dbus.h"
#include <gio/gunixfdlist.h>
#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);
}

View file

@ -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);

View file

@ -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;

View file

@ -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
}

View file

@ -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

View file

@ -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());

View file

@ -1,4 +1,3 @@
#version 300 es
in vec2 in_position;

View file

@ -1,4 +1,3 @@
#version 300 es
uniform sampler2D image;

View file

@ -1,4 +1,3 @@
#version 300 es
in vec2 in_position;

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -159,7 +159,6 @@ struct VncDisplay
QKbdState *kbd;
QemuMutex mutex;
QEMUCursor *cursor;
int cursor_msize;
uint8_t *cursor_mask;