Narrows release_dmabuf to the active scanout, as the device & console may interleave new scanouts before releasing old ones.
Signed-off-by: Marc-André Lureau <[email protected]> --- ui/dbus-listener.c | 68 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c index 2e2f6ba4183a..5a72c7eeae59 100644 --- a/ui/dbus-listener.c +++ b/ui/dbus-listener.c @@ -91,6 +91,8 @@ struct _DBusDisplayListener { guint dbus_filter; guint32 display_serial_to_discard; guint32 cursor_serial_to_discard; + + QemuDmaBuf *scanout_dmabuf; }; G_DEFINE_TYPE(DBusDisplayListener, dbus_display_listener, G_TYPE_OBJECT) @@ -119,6 +121,7 @@ static void dbus_scanout_disable(DisplayChangeListener *dcl) { DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + ddl->scanout_dmabuf = NULL; ddl_discard_display_messages(ddl); qemu_dbus_display1_listener_call_disable( @@ -298,9 +301,9 @@ static void dbus_call_update_gl(DisplayChangeListener *dcl, #ifdef CONFIG_GBM static void dbus_scanout_dmabuf_v1(DBusDisplayListener *ddl, - QemuDmaBuf *dmabuf) + QemuDmaBuf *dmabuf, + GError **err) { - g_autoptr(GError) err = NULL; g_autoptr(GUnixFDList) fd_list = NULL; int fd; uint32_t width, height, stride, fourcc; @@ -309,8 +312,7 @@ static void dbus_scanout_dmabuf_v1(DBusDisplayListener *ddl, fd = qemu_dmabuf_get_fds(dmabuf, NULL)[0]; fd_list = g_unix_fd_list_new(); - if (g_unix_fd_list_append(fd_list, fd, &err) != 0) { - error_report("Failed to setup dmabuf fdlist: %s", err->message); + if (g_unix_fd_list_append(fd_list, fd, err) != 0) { return; } @@ -332,9 +334,9 @@ static void dbus_scanout_dmabuf_v1(DBusDisplayListener *ddl, } static void dbus_scanout_dmabuf_v2(DBusDisplayListener *ddl, - QemuDmaBuf *dmabuf) + QemuDmaBuf *dmabuf, + GError **err) { - g_autoptr(GError) err = NULL; g_autoptr(GUnixFDList) fd_list = NULL; int i, fd_index[DMABUF_MAX_PLANES], num_fds; uint32_t x, y, width, height, fourcc, backing_width, backing_height; @@ -360,9 +362,8 @@ static void dbus_scanout_dmabuf_v2(DBusDisplayListener *ddl, break; } - fd_index[num_fds] = g_unix_fd_list_append(fd_list, plane_fd, &err); + fd_index[num_fds] = g_unix_fd_list_append(fd_list, plane_fd, err); if (fd_index[num_fds] < 0) { - error_report("Failed to setup dmabuf fdlist: %s", err->message); return; } } @@ -395,20 +396,36 @@ static void dbus_scanout_dmabuf_v2(DBusDisplayListener *ddl, G_DBUS_CALL_FLAGS_NONE, -1, fd_list, NULL, NULL, NULL); } +static bool dbus_call_scanout_dmabuf(DBusDisplayListener *ddl, + QemuDmaBuf *dmabuf) +{ + g_autoptr(GError) err = NULL; + + if (ddl->scanout_dmabuf_v2_proxy) { + dbus_scanout_dmabuf_v2(ddl, dmabuf, &err); + } else { + if (qemu_dmabuf_get_num_planes(dmabuf) > 1) { + error_report("Peer does not support multi plane dmabuf"); + return false; + } + dbus_scanout_dmabuf_v1(ddl, dmabuf, &err); + } + + if (err) { + error_report("Failed to scanout dmabuf: %s", err->message); + return false; + } + + return true; +} + static void dbus_scanout_dmabuf(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf) { DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); - if (ddl->scanout_dmabuf_v2_proxy) { - dbus_scanout_dmabuf_v2(ddl, dmabuf); - } else { - if (qemu_dmabuf_get_num_planes(dmabuf) > 1) { - g_debug("org.qemu.Display1.Listener.ScanoutDMABUF " - "does not support mutli plane"); - return; - } - dbus_scanout_dmabuf_v1(ddl, dmabuf); + if (dbus_call_scanout_dmabuf(ddl, dmabuf)) { + ddl->scanout_dmabuf = dmabuf; } } #endif /* GBM */ @@ -589,6 +606,10 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl, uint32_t w, uint32_t h, void *d3d_tex2d) { +#if defined(CONFIG_GBM) || defined(WIN32) + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); +#endif + trace_dbus_scanout_texture(tex_id, backing_y_0_top, backing_width, backing_height, x, y, w, h); #ifdef CONFIG_GBM @@ -607,13 +628,13 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl, backing_height, fourcc, modifier, fd, num_planes, false, backing_y_0_top); - dbus_scanout_dmabuf(dcl, dmabuf); + if (dbus_call_scanout_dmabuf(ddl, dmabuf)) { + ddl->scanout_dmabuf = NULL; + } qemu_dmabuf_close(dmabuf); #endif #ifdef WIN32 - DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); - /* there must be a matching gfx_switch before */ assert(surface_width(ddl->ds) == w); assert(surface_height(ddl->ds) == h); @@ -686,7 +707,14 @@ static void dbus_cursor_dmabuf(DisplayChangeListener *dcl, static void dbus_release_dmabuf(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf) { + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + + if (ddl->scanout_dmabuf != dmabuf) { + return; + } + dbus_scanout_disable(dcl); + ddl->scanout_dmabuf = NULL; } #endif /* GBM */ -- 2.55.0.543.g5ebe2ebe4ea8
