mirror of https://github.com/xemu-project/xemu.git
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:
commit
7c3cc428c7
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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') \
|
||||
|
|
|
@ -101,7 +101,7 @@ qtests_i386 = \
|
|||
'numa-test'
|
||||
]
|
||||
|
||||
if dbus_display
|
||||
if dbus_display and targetos != 'windows'
|
||||
qtests_i386 += ['dbus-display-test']
|
||||
endif
|
||||
|
||||
|
|
18
ui/console.c
18
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
29
ui/dbus.c
29
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
26
ui/sdl2.c
26
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());
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#version 300 es
|
||||
|
||||
in vec2 in_position;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#version 300 es
|
||||
|
||||
uniform sampler2D image;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#version 300 es
|
||||
|
||||
in vec2 in_position;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
8
ui/vnc.c
8
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);
|
||||
|
|
Loading…
Reference in New Issue