@@ -33,11 +33,10 @@
struct _DBusDisplayConsole {
GDBusObjectSkeleton parent_instance;
- DisplayChangeListener dcl;
DBusDisplay *display;
QemuConsole *con;
- GHashTable *listeners;
+ DBusDisplayListener *listener;
QemuDBusDisplay1Console *iface;
QemuDBusDisplay1Keyboard *iface_kbd;
@@ -54,7 +53,7 @@ G_DEFINE_TYPE(DBusDisplayConsole,
dbus_display_console,
G_TYPE_DBUS_OBJECT_SKELETON)
-static void
+void
dbus_display_console_set_size(DBusDisplayConsole *ddc,
uint32_t width, uint32_t height)
{
@@ -64,78 +63,9 @@ dbus_display_console_set_size(DBusDisplayConsole *ddc,
NULL);
}
-static void
-dbus_gfx_switch(DisplayChangeListener *dcl,
- struct DisplaySurface *new_surface)
-{
- DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl);
-
- dbus_display_console_set_size(ddc,
- surface_width(new_surface),
- surface_height(new_surface));
-}
-
-static void
-dbus_gfx_update(DisplayChangeListener *dcl,
- int x, int y, int w, int h)
-{
-}
-
-static void
-dbus_gl_scanout_disable(DisplayChangeListener *dcl)
-{
-}
-
-static void
-dbus_gl_scanout_texture(DisplayChangeListener *dcl,
- uint32_t tex_id,
- bool backing_y_0_top,
- uint32_t backing_width,
- uint32_t backing_height,
- uint32_t x, uint32_t y,
- uint32_t w, uint32_t h)
-{
- DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl);
-
- dbus_display_console_set_size(ddc, w, h);
-}
-
-static void
-dbus_gl_scanout_dmabuf(DisplayChangeListener *dcl,
- QemuDmaBuf *dmabuf)
-{
- DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl);
-
- dbus_display_console_set_size(ddc,
- dmabuf->width,
- dmabuf->height);
-}
-
-static void
-dbus_gl_scanout_update(DisplayChangeListener *dcl,
- uint32_t x, uint32_t y,
- uint32_t w, uint32_t h)
-{
-}
-
-static const DisplayChangeListenerOps dbus_console_dcl_ops = {
- .dpy_name = "dbus-console",
- .dpy_gfx_switch = dbus_gfx_switch,
- .dpy_gfx_update = dbus_gfx_update,
- .dpy_gl_scanout_disable = dbus_gl_scanout_disable,
- .dpy_gl_scanout_texture = dbus_gl_scanout_texture,
- .dpy_gl_scanout_dmabuf = dbus_gl_scanout_dmabuf,
- .dpy_gl_update = dbus_gl_scanout_update,
-};
-
static void
dbus_display_console_init(DBusDisplayConsole *object)
{
- DBusDisplayConsole *ddc = DBUS_DISPLAY_CONSOLE(object);
-
- ddc->listeners = g_hash_table_new_full(g_str_hash, g_str_equal,
- NULL, g_object_unref);
- ddc->dcl.ops = &dbus_console_dcl_ops;
}
static void
@@ -143,10 +73,10 @@ dbus_display_console_dispose(GObject *object)
{
DBusDisplayConsole *ddc = DBUS_DISPLAY_CONSOLE(object);
- unregister_displaychangelistener(&ddc->dcl);
g_clear_object(&ddc->iface_kbd);
g_clear_object(&ddc->iface);
- g_clear_pointer(&ddc->listeners, g_hash_table_unref);
+ dbus_display_listener_unref_all_connections(ddc->listener);
+ g_clear_object(&ddc->listener);
g_clear_pointer(&ddc->kbd, qkbd_state_free);
G_OBJECT_CLASS(dbus_display_console_parent_class)->dispose(object);
@@ -161,14 +91,14 @@ dbus_display_console_class_init(DBusDisplayConsoleClass *klass)
}
static void
-listener_vanished_cb(DBusDisplayListener *listener)
+listener_vanished_cb(DBusDisplayListenerConnection *ddlc)
{
- DBusDisplayConsole *ddc = dbus_display_listener_get_console(listener);
- const char *name = dbus_display_listener_get_bus_name(listener);
+ DBusDisplayConsole *ddc = dbus_display_listener_connection_get_console(ddlc);
+ const char *name = dbus_display_listener_connection_get_bus_name(ddlc);
trace_dbus_listener_vanished(name);
- g_hash_table_remove(ddc->listeners, name);
+ g_object_unref(ddlc);
qkbd_state_lift_all_keys(ddc->kbd);
}
@@ -211,15 +141,15 @@ dbus_console_register_listener(DBusDisplayConsole *ddc,
GVariant *arg_listener)
{
const char *sender = g_dbus_method_invocation_get_sender(invocation);
- GDBusConnection *listener_conn;
+ GDBusConnection *conn;
g_autoptr(GError) err = NULL;
g_autoptr(GSocket) socket = NULL;
g_autoptr(GSocketConnection) socket_conn = NULL;
g_autofree char *guid = g_dbus_generate_guid();
- DBusDisplayListener *listener;
+ DBusDisplayListenerConnection *listener_conn;
int fd;
- if (sender && g_hash_table_contains(ddc->listeners, sender)) {
+ if (sender && dbus_display_listener_has_connection(ddc->listener, sender)) {
g_dbus_method_invocation_return_error(
invocation,
DBUS_DISPLAY_ERROR,
@@ -254,7 +184,7 @@ dbus_console_register_listener(DBusDisplayConsole *ddc,
qemu_dbus_display1_console_complete_register_listener(
ddc->iface, invocation, NULL);
- listener_conn = g_dbus_connection_new_sync(
+ conn = g_dbus_connection_new_sync(
G_IO_STREAM(socket_conn),
guid,
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
@@ -264,16 +194,15 @@ dbus_console_register_listener(DBusDisplayConsole *ddc,
return DBUS_METHOD_INVOCATION_HANDLED;
}
- listener = dbus_display_listener_new(sender, listener_conn, ddc);
- if (!listener) {
+ listener_conn = dbus_display_listener_add_connection(ddc->listener,
+ sender, conn);
+ if (!listener_conn) {
return DBUS_METHOD_INVOCATION_HANDLED;
}
- g_hash_table_insert(ddc->listeners,
- (gpointer)dbus_display_listener_get_bus_name(listener),
- listener);
- g_object_connect(listener_conn,
- "swapped-signal::closed", listener_vanished_cb, listener,
+ g_object_connect(conn,
+ "swapped-signal::closed", listener_vanished_cb,
+ listener_conn,
NULL);
trace_dbus_registered_listener(sender);
@@ -489,7 +418,7 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con)
g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(ddc),
G_DBUS_INTERFACE_SKELETON(ddc->iface_mouse));
- register_displaychangelistener(&ddc->dcl);
+ ddc->listener = dbus_display_listener_new(ddc);
ddc->mouse_mode_notifier.notify = dbus_mouse_mode_change;
qemu_add_mouse_mode_change_notifier(&ddc->mouse_mode_notifier);
@@ -31,18 +31,36 @@
#include "ui/egl-context.h"
#include "trace.h"
-struct _DBusDisplayListener {
+struct _DBusDisplayListenerConnection {
GObject parent;
char *bus_name;
- DBusDisplayConsole *console;
+ DBusDisplayListener *listener;
GDBusConnection *conn;
QemuDBusDisplay1Listener *proxy;
+};
+
+G_DEFINE_TYPE(DBusDisplayListenerConnection,
+ dbus_display_listener_connection,
+ G_TYPE_OBJECT)
+
+struct _DBusDisplayListener {
+ GObject parent;
+
+ GHashTable *conns;
+ DBusDisplayConsole *console;
DisplayChangeListener dcl;
DisplaySurface *ds;
QemuGLShader *gls;
+ GUnixFDList *dmabuf_fd_list;
+ uint32_t dmabuf_width;
+ uint32_t dmabuf_height;
+ uint32_t dmabuf_stride;
+ uint32_t dmabuf_fourcc;
+ uint64_t dmabuf_modifier;
+ bool dmabuf_y0_top;
int gl_updates;
};
@@ -53,65 +71,98 @@ static void dbus_update_gl_cb(GObject *source_object,
gpointer user_data)
{
g_autoptr(GError) err = NULL;
- DBusDisplayListener *ddl = user_data;
+ DBusDisplayListenerConnection *ddlc = user_data;
- if (!qemu_dbus_display1_listener_call_update_dmabuf_finish(ddl->proxy,
+ if (!qemu_dbus_display1_listener_call_update_dmabuf_finish(ddlc->proxy,
res, &err)) {
error_report("Failed to call update: %s", err->message);
}
- graphic_hw_gl_block(ddl->dcl.con, false);
- g_object_unref(ddl);
+ graphic_hw_gl_block(ddlc->listener->dcl.con, false);
+ g_object_unref(ddlc);
}
static void dbus_call_update_gl(DBusDisplayListener *ddl,
int x, int y, int w, int h)
{
- graphic_hw_gl_block(ddl->dcl.con, true);
- glFlush();
- qemu_dbus_display1_listener_call_update_dmabuf(ddl->proxy,
- x, y, w, h,
- G_DBUS_CALL_FLAGS_NONE,
- DBUS_DEFAULT_TIMEOUT, NULL,
- dbus_update_gl_cb,
- g_object_ref(ddl));
+ GHashTableIter iter;
+ gpointer ddlc;
+
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ graphic_hw_gl_block(ddl->dcl.con, true);
+ glFlush();
+ qemu_dbus_display1_listener_call_update_dmabuf(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ x, y, w, h,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_DEFAULT_TIMEOUT, NULL,
+ dbus_update_gl_cb,
+ g_object_ref(ddlc));
+ }
}
static void dbus_scanout_disable(DisplayChangeListener *dcl)
{
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
+ GHashTableIter iter;
+ gpointer ddlc;
ddl->ds = NULL;
- qemu_dbus_display1_listener_call_disable(
- ddl->proxy, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ qemu_dbus_display1_listener_call_disable(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+ }
}
static void dbus_scanout_dmabuf(DisplayChangeListener *dcl,
QemuDmaBuf *dmabuf)
{
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
+ GHashTableIter iter;
+ gpointer ddlc;
g_autoptr(GError) err = NULL;
g_autoptr(GUnixFDList) fd_list = NULL;
- fd_list = g_unix_fd_list_new();
- if (g_unix_fd_list_append(fd_list, dmabuf->fd, &err) != 0) {
+ if (ddl->dmabuf_fd_list) {
+ g_clear_object(&ddl->dmabuf_fd_list);
+ }
+
+ ddl->dmabuf_fd_list = g_unix_fd_list_new();
+ if (g_unix_fd_list_append(ddl->dmabuf_fd_list, dmabuf->fd, &err) != 0) {
+ g_clear_object(&ddl->dmabuf_fd_list);
error_report("Failed to setup dmabuf fdlist: %s", err->message);
return;
}
- qemu_dbus_display1_listener_call_scanout_dmabuf(
- ddl->proxy,
- g_variant_new_handle(0),
- dmabuf->width,
- dmabuf->height,
- dmabuf->stride,
- dmabuf->fourcc,
- dmabuf->modifier,
- dmabuf->y0_top,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- fd_list,
- NULL, NULL, NULL);
+ ddl->dmabuf_width = dmabuf->width;
+ ddl->dmabuf_height = dmabuf->height;
+ ddl->dmabuf_stride = dmabuf->stride;
+ ddl->dmabuf_fourcc = dmabuf->fourcc;
+ ddl->dmabuf_modifier = dmabuf->modifier;
+ ddl->dmabuf_y0_top = dmabuf->y0_top;
+
+ dbus_display_console_set_size(ddl->console, dmabuf->width, dmabuf->height);
+
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ qemu_dbus_display1_listener_call_scanout_dmabuf(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ g_variant_new_handle(0),
+ ddl->dmabuf_width,
+ ddl->dmabuf_height,
+ ddl->dmabuf_stride,
+ ddl->dmabuf_fourcc,
+ ddl->dmabuf_modifier,
+ ddl->dmabuf_y0_top,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ ddl->dmabuf_fd_list,
+ NULL, NULL, NULL);
+ }
}
static void dbus_scanout_texture(DisplayChangeListener *dcl,
@@ -150,11 +201,16 @@ static void dbus_cursor_dmabuf(DisplayChangeListener *dcl,
DisplaySurface *ds;
GVariant *v_data = NULL;
egl_fb cursor_fb;
+ GHashTableIter iter;
+ gpointer ddlc;
if (!dmabuf) {
- qemu_dbus_display1_listener_call_mouse_set(
- ddl->proxy, 0, 0, false,
- G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ qemu_dbus_display1_listener_call_mouse_set(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy, 0, 0, false,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+ }
return;
}
@@ -174,28 +230,37 @@ static void dbus_cursor_dmabuf(DisplayChangeListener *dcl,
TRUE,
(GDestroyNotify)qemu_free_displaysurface,
ds);
- qemu_dbus_display1_listener_call_cursor_define(
- ddl->proxy,
- surface_width(ds),
- surface_height(ds),
- hot_x,
- hot_y,
- v_data,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL,
- NULL);
+
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ qemu_dbus_display1_listener_call_cursor_define(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ surface_width(ds),
+ surface_height(ds),
+ hot_x,
+ hot_y,
+ v_data,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ NULL);
+ }
}
static void dbus_cursor_position(DisplayChangeListener *dcl,
uint32_t pos_x, uint32_t pos_y)
{
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
+ GHashTableIter iter;
+ gpointer ddlc;
- qemu_dbus_display1_listener_call_mouse_set(
- ddl->proxy, pos_x, pos_y, true,
- G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ qemu_dbus_display1_listener_call_mouse_set(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ pos_x, pos_y, true, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+ }
}
static void dbus_release_dmabuf(DisplayChangeListener *dcl,
@@ -254,6 +319,8 @@ static void dbus_gfx_update(DisplayChangeListener *dcl,
pixman_image_t *img;
GVariant *v_data;
size_t stride;
+ GHashTableIter iter;
+ gpointer ddlc;
assert(ddl->ds);
stride = w * DIV_ROUND_UP(PIXMAN_FORMAT_BPP(surface_format(ddl->ds)), 8);
@@ -273,11 +340,16 @@ static void dbus_gfx_update(DisplayChangeListener *dcl,
TRUE,
(GDestroyNotify)pixman_image_unref,
img);
- qemu_dbus_display1_listener_call_update(ddl->proxy,
- x, y, w, h, pixman_image_get_stride(img), pixman_image_get_format(img),
- v_data,
- G_DBUS_CALL_FLAGS_NONE,
- DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
+
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ qemu_dbus_display1_listener_call_update(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ x, y, w, h, pixman_image_get_stride(img), pixman_image_get_format(img),
+ v_data,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
+ }
}
static void dbus_gl_gfx_switch(DisplayChangeListener *dcl,
@@ -293,6 +365,8 @@ static void dbus_gl_gfx_switch(DisplayChangeListener *dcl,
int width = surface_width(ddl->ds);
int height = surface_height(ddl->ds);
+ dbus_display_console_set_size(ddl->console, width, height);
+
surface_gl_create_texture(ddl->gls, ddl->ds);
/* TODO: lazy send dmabuf (there are unnecessary sent otherwise) */
dbus_scanout_texture(&ddl->dcl, ddl->ds->texture, false,
@@ -305,6 +379,8 @@ static void dbus_gfx_switch(DisplayChangeListener *dcl,
{
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
GVariant *v_data = NULL;
+ GHashTableIter iter;
+ gpointer ddlc;
ddl->ds = new_surface;
if (!ddl->ds) {
@@ -312,6 +388,10 @@ static void dbus_gfx_switch(DisplayChangeListener *dcl,
return;
}
+ dbus_display_console_set_size(ddl->console,
+ surface_width(ddl->ds),
+ surface_height(ddl->ds));
+
v_data = g_variant_new_from_data(
G_VARIANT_TYPE("ay"),
surface_data(ddl->ds),
@@ -319,23 +399,34 @@ static void dbus_gfx_switch(DisplayChangeListener *dcl,
TRUE,
(GDestroyNotify)pixman_image_unref,
pixman_image_ref(ddl->ds->image));
- qemu_dbus_display1_listener_call_scanout(ddl->proxy,
- surface_width(ddl->ds),
- surface_height(ddl->ds),
- surface_stride(ddl->ds),
- surface_format(ddl->ds),
- v_data,
- G_DBUS_CALL_FLAGS_NONE,
- DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
+
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ qemu_dbus_display1_listener_call_scanout(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ surface_width(ddl->ds),
+ surface_height(ddl->ds),
+ surface_stride(ddl->ds),
+ surface_format(ddl->ds),
+ v_data,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
+ }
}
static void dbus_mouse_set(DisplayChangeListener *dcl,
int x, int y, int on)
{
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
+ GHashTableIter iter;
+ gpointer ddlc;
- qemu_dbus_display1_listener_call_mouse_set(
- ddl->proxy, x, y, on, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ qemu_dbus_display1_listener_call_mouse_set(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ x, y, on, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+ }
}
static void dbus_cursor_define(DisplayChangeListener *dcl,
@@ -343,6 +434,8 @@ static void dbus_cursor_define(DisplayChangeListener *dcl,
{
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
GVariant *v_data = NULL;
+ GHashTableIter iter;
+ gpointer ddlc;
cursor_get(c);
v_data = g_variant_new_from_data(
@@ -353,18 +446,21 @@ static void dbus_cursor_define(DisplayChangeListener *dcl,
(GDestroyNotify)cursor_put,
c);
- qemu_dbus_display1_listener_call_cursor_define(
- ddl->proxy,
- c->width,
- c->height,
- c->hot_x,
- c->hot_y,
- v_data,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL,
- NULL);
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ qemu_dbus_display1_listener_call_cursor_define(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ c->width,
+ c->height,
+ c->hot_x,
+ c->hot_y,
+ v_data,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ NULL);
+ }
}
const DisplayChangeListenerOps dbus_gl_dcl_ops = {
@@ -400,9 +496,8 @@ dbus_display_listener_dispose(GObject *object)
DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object);
unregister_displaychangelistener(&ddl->dcl);
- g_clear_object(&ddl->conn);
- g_clear_pointer(&ddl->bus_name, g_free);
- g_clear_object(&ddl->proxy);
+ g_clear_object(&ddl->dmabuf_fd_list);
+ g_clear_pointer(&ddl->conns, g_hash_table_unref);
g_clear_pointer(&ddl->gls, qemu_gl_fini_shader);
G_OBJECT_CLASS(dbus_display_listener_parent_class)->dispose(object);
@@ -435,46 +530,146 @@ dbus_display_listener_class_init(DBusDisplayListenerClass *klass)
static void
dbus_display_listener_init(DBusDisplayListener *ddl)
{
+ ddl->conns = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
}
-const char *
-dbus_display_listener_get_bus_name(DBusDisplayListener *ddl)
-{
- return ddl->bus_name ?: "p2p";
-}
-
-DBusDisplayConsole *
-dbus_display_listener_get_console(DBusDisplayListener *ddl)
+DBusDisplayListenerConnection *
+dbus_display_listener_add_connection(DBusDisplayListener *ddl,
+ const char *bus_name,
+ GDBusConnection *conn)
{
- return ddl->console;
-}
-
-DBusDisplayListener *
-dbus_display_listener_new(const char *bus_name,
- GDBusConnection *conn,
- DBusDisplayConsole *console)
-{
- DBusDisplayListener *ddl;
- QemuConsole *con;
+ DBusDisplayListenerConnection *ddlc;
+ QemuDBusDisplay1Listener *proxy;
g_autoptr(GError) err = NULL;
- ddl = g_object_new(DBUS_DISPLAY_TYPE_LISTENER, NULL);
- ddl->proxy =
+ proxy =
qemu_dbus_display1_listener_proxy_new_sync(conn,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
NULL,
"/org/qemu/Display1/Listener",
NULL,
&err);
- if (!ddl->proxy) {
+ if (!proxy) {
error_report("Failed to setup proxy: %s", err->message);
g_object_unref(conn);
- g_object_unref(ddl);
return NULL;
}
- ddl->bus_name = g_strdup(bus_name);
- ddl->conn = conn;
+ ddlc = g_object_new(DBUS_DISPLAY_TYPE_LISTENER_CONNECTION, NULL);
+ ddlc->listener = g_object_ref(ddl);
+ ddlc->proxy = proxy;
+ ddlc->bus_name = g_strdup(bus_name);
+ ddlc->conn = conn;
+
+ g_hash_table_insert(ddl->conns, ddlc->bus_name, ddlc);
+
+ if (display_opengl) {
+ if (ddl->dmabuf_fd_list) {
+ qemu_dbus_display1_listener_call_scanout_dmabuf(
+ ddlc->proxy,
+ g_variant_new_handle(0),
+ ddl->dmabuf_width,
+ ddl->dmabuf_height,
+ ddl->dmabuf_stride,
+ ddl->dmabuf_fourcc,
+ ddl->dmabuf_modifier,
+ ddl->dmabuf_y0_top,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ ddl->dmabuf_fd_list,
+ NULL, NULL, NULL);
+ }
+ } else {
+ if (ddl->ds) {
+ GVariant *v_data = NULL;
+
+ v_data = g_variant_new_from_data(
+ G_VARIANT_TYPE("ay"),
+ surface_data(ddl->ds),
+ surface_stride(ddl->ds) * surface_height(ddl->ds),
+ TRUE,
+ (GDestroyNotify)pixman_image_unref,
+ pixman_image_ref(ddl->ds->image));
+
+ qemu_dbus_display1_listener_call_scanout(
+ ((DBusDisplayListenerConnection *)ddlc)->proxy,
+ surface_width(ddl->ds),
+ surface_height(ddl->ds),
+ surface_stride(ddl->ds),
+ surface_format(ddl->ds),
+ v_data,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
+ }
+ }
+
+ return ddlc;
+}
+
+bool
+dbus_display_listener_has_connection(DBusDisplayListener *ddl,
+ const char *bus_name)
+{
+ return g_hash_table_contains(ddl->conns, bus_name);
+}
+
+void
+dbus_display_listener_unref_all_connections(DBusDisplayListener *ddl)
+{
+ GHashTableIter iter;
+ gpointer ddlc;
+
+ g_hash_table_iter_init(&iter, ddl->conns);
+ while (g_hash_table_iter_next(&iter, NULL, &ddlc)) {
+ g_object_unref(ddlc);
+ }
+}
+
+static void
+dbus_display_listener_connection_dispose(GObject *object)
+{
+ DBusDisplayListenerConnection *ddlc =
+ DBUS_DISPLAY_LISTENER_CONNECTION(object);
+
+ g_hash_table_remove(ddlc->listener->conns, ddlc->bus_name);
+ g_clear_object(&ddlc->listener);
+ g_clear_object(&ddlc->conn);
+ g_clear_pointer(&ddlc->bus_name, g_free);
+ g_clear_object(&ddlc->proxy);
+
+ G_OBJECT_CLASS(dbus_display_listener_connection_parent_class)->dispose(object);
+}
+
+static void
+dbus_display_listener_connection_class_init(DBusDisplayListenerConnectionClass *klass)
+{
+ G_OBJECT_CLASS(klass)->dispose = dbus_display_listener_connection_dispose;
+}
+
+static void
+dbus_display_listener_connection_init(DBusDisplayListenerConnection *ddl)
+{
+}
+
+const char *
+dbus_display_listener_connection_get_bus_name(DBusDisplayListenerConnection *ddlc)
+{
+ return ddlc->bus_name ?: "p2p";
+}
+
+DBusDisplayConsole *
+dbus_display_listener_connection_get_console(DBusDisplayListenerConnection *ddlc)
+{
+ return ddlc->listener->console;
+}
+
+DBusDisplayListener *
+dbus_display_listener_new(DBusDisplayConsole *console)
+{
+ DBusDisplayListener *ddl;
+ QemuConsole *con;
+
+ ddl = g_object_new(DBUS_DISPLAY_TYPE_LISTENER, NULL);
ddl->console = console;
con = qemu_console_lookup_by_index(dbus_display_console_get_index(console));
@@ -76,9 +76,19 @@ G_DECLARE_FINAL_TYPE(DBusDisplayConsole,
DBusDisplayConsole *
dbus_display_console_new(DBusDisplay *display, QemuConsole *con);
+void
+dbus_display_console_set_size(DBusDisplayConsole *ddc,
+ uint32_t width, uint32_t height);
+
int
dbus_display_console_get_index(DBusDisplayConsole *ddc);
+G_DECLARE_FINAL_TYPE(DBusDisplayListenerConnection,
+ dbus_display_listener_connection,
+ DBUS_DISPLAY,
+ LISTENER_CONNECTION,
+ GObject)
+
#define DBUS_DISPLAY_TYPE_LISTENER dbus_display_listener_get_type()
G_DECLARE_FINAL_TYPE(DBusDisplayListener,
dbus_display_listener,
@@ -86,16 +96,28 @@ G_DECLARE_FINAL_TYPE(DBusDisplayListener,
LISTENER,
GObject)
+#define DBUS_DISPLAY_TYPE_LISTENER_CONNECTION \
+ dbus_display_listener_connection_get_type()
DBusDisplayListener *
-dbus_display_listener_new(const char *bus_name,
- GDBusConnection *conn,
- DBusDisplayConsole *console);
+dbus_display_listener_new(DBusDisplayConsole *console);
+
+DBusDisplayListenerConnection *
+dbus_display_listener_add_connection(DBusDisplayListener *ddl,
+ const char *bus_name,
+ GDBusConnection *conn);
+
+bool
+dbus_display_listener_has_connection(DBusDisplayListener *ddl,
+ const char *bus_name);
+
+void
+dbus_display_listener_unref_all_connections(DBusDisplayListener *ddl);
DBusDisplayConsole *
-dbus_display_listener_get_console(DBusDisplayListener *ddl);
+dbus_display_listener_connection_get_console(DBusDisplayListenerConnection *ddlc);
const char *
-dbus_display_listener_get_bus_name(DBusDisplayListener *ddl);
+dbus_display_listener_connection_get_bus_name(DBusDisplayListenerConnection *ddlc);
extern const DisplayChangeListenerOps dbus_gl_dcl_ops;
extern const DisplayChangeListenerOps dbus_dcl_ops;
This fixes surface texture double free with multiple connections and out-of-sync display size with multiple displays. This also reduces resource usage a little and allows to remove code to support multiple listeners for OpenGL displays. Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com> --- ui/dbus-console.c | 109 +++--------- ui/dbus-listener.c | 401 +++++++++++++++++++++++++++++++++------------ ui/dbus.h | 32 +++- 3 files changed, 344 insertions(+), 198 deletions(-)