|
|
|
@ -85,6 +85,7 @@ struct _DBusDisplayListener { |
|
|
|
#endif |
|
|
|
#else /* !WIN32 */ |
|
|
|
QemuDBusDisplay1ListenerUnixMap *map_proxy; |
|
|
|
QemuDBusDisplay1ListenerUnixScanoutDMABUF2 *scanout_dmabuf_v2_proxy; |
|
|
|
#endif |
|
|
|
|
|
|
|
guint dbus_filter; |
|
|
|
@ -288,10 +289,9 @@ static void dbus_call_update_gl(DisplayChangeListener *dcl, |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef CONFIG_GBM |
|
|
|
static void dbus_scanout_dmabuf(DisplayChangeListener *dcl, |
|
|
|
QemuDmaBuf *dmabuf) |
|
|
|
static void dbus_scanout_dmabuf_v1(DBusDisplayListener *ddl, |
|
|
|
QemuDmaBuf *dmabuf) |
|
|
|
{ |
|
|
|
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); |
|
|
|
g_autoptr(GError) err = NULL; |
|
|
|
g_autoptr(GUnixFDList) fd_list = NULL; |
|
|
|
int fd; |
|
|
|
@ -322,6 +322,87 @@ static void dbus_scanout_dmabuf(DisplayChangeListener *dcl, |
|
|
|
y0_top, G_DBUS_CALL_FLAGS_NONE, |
|
|
|
-1, fd_list, NULL, NULL, NULL); |
|
|
|
} |
|
|
|
|
|
|
|
static void dbus_scanout_dmabuf_v2(DBusDisplayListener *ddl, |
|
|
|
QemuDmaBuf *dmabuf) |
|
|
|
{ |
|
|
|
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; |
|
|
|
GVariant *fd, *offset, *stride, *fd_handles[DMABUF_MAX_PLANES]; |
|
|
|
uint64_t modifier; |
|
|
|
bool y0_top; |
|
|
|
int nfds, noffsets, nstrides; |
|
|
|
const int *fds = qemu_dmabuf_get_fds(dmabuf, &nfds); |
|
|
|
const uint32_t *offsets = qemu_dmabuf_get_offsets(dmabuf, &noffsets); |
|
|
|
const uint32_t *strides = qemu_dmabuf_get_strides(dmabuf, &nstrides); |
|
|
|
uint32_t num_planes = qemu_dmabuf_get_num_planes(dmabuf); |
|
|
|
|
|
|
|
assert(nfds >= num_planes); |
|
|
|
assert(noffsets >= num_planes); |
|
|
|
assert(nstrides >= num_planes); |
|
|
|
|
|
|
|
fd_list = g_unix_fd_list_new(); |
|
|
|
|
|
|
|
for (num_fds = 0; num_fds < num_planes; num_fds++) { |
|
|
|
int plane_fd = fds[num_fds]; |
|
|
|
|
|
|
|
if (plane_fd < 0) { |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ddl_discard_display_messages(ddl); |
|
|
|
|
|
|
|
x = qemu_dmabuf_get_x(dmabuf); |
|
|
|
y = qemu_dmabuf_get_y(dmabuf); |
|
|
|
width = qemu_dmabuf_get_width(dmabuf); |
|
|
|
height = qemu_dmabuf_get_height(dmabuf); |
|
|
|
fourcc = qemu_dmabuf_get_fourcc(dmabuf); |
|
|
|
backing_width = qemu_dmabuf_get_backing_width(dmabuf); |
|
|
|
backing_height = qemu_dmabuf_get_backing_height(dmabuf); |
|
|
|
modifier = qemu_dmabuf_get_modifier(dmabuf); |
|
|
|
y0_top = qemu_dmabuf_get_y0_top(dmabuf); |
|
|
|
|
|
|
|
offset = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, |
|
|
|
offsets, num_planes, sizeof(uint32_t)); |
|
|
|
stride = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, |
|
|
|
strides, num_planes, sizeof(uint32_t)); |
|
|
|
|
|
|
|
for (i = 0; i < num_fds; i++) { |
|
|
|
fd_handles[i] = g_variant_new_handle(fd_index[i]); |
|
|
|
} |
|
|
|
fd = g_variant_new_array(G_VARIANT_TYPE_HANDLE, fd_handles, num_fds); |
|
|
|
|
|
|
|
qemu_dbus_display1_listener_unix_scanout_dmabuf2_call_scanout_dmabuf2( |
|
|
|
ddl->scanout_dmabuf_v2_proxy, fd, x, y, width, height, offset, stride, |
|
|
|
num_planes, fourcc, backing_width, backing_height, modifier, y0_top, |
|
|
|
G_DBUS_CALL_FLAGS_NONE, -1, fd_list, NULL, NULL, NULL); |
|
|
|
} |
|
|
|
|
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif /* GBM */ |
|
|
|
#endif /* OPENGL */ |
|
|
|
|
|
|
|
@ -514,10 +595,6 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl, |
|
|
|
error_report("%s: failed to export dmabuf for texture", __func__); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (num_planes > 1) { |
|
|
|
error_report("%s: does not support multi-plane dmabuf", __func__); |
|
|
|
return; |
|
|
|
} |
|
|
|
dmabuf = qemu_dmabuf_new(w, h, offset, stride, x, y, backing_width, |
|
|
|
backing_height, fourcc, modifier, fd, num_planes, |
|
|
|
false, backing_y_0_top); |
|
|
|
@ -886,6 +963,8 @@ dbus_display_listener_dispose(GObject *object) |
|
|
|
#ifdef CONFIG_OPENGL |
|
|
|
egl_fb_destroy(&ddl->fb); |
|
|
|
#endif |
|
|
|
#else /* !WIN32 */ |
|
|
|
g_clear_object(&ddl->scanout_dmabuf_v2_proxy); |
|
|
|
#endif |
|
|
|
|
|
|
|
G_OBJECT_CLASS(dbus_display_listener_parent_class)->dispose(object); |
|
|
|
@ -1074,6 +1153,26 @@ dbus_display_listener_setup_shared_map(DBusDisplayListener *ddl) |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
static void dbus_display_listener_setup_scanout_dmabuf_v2(DBusDisplayListener *ddl) |
|
|
|
{ |
|
|
|
#ifndef WIN32 |
|
|
|
g_autoptr(GError) err = NULL; |
|
|
|
|
|
|
|
if (!dbus_display_listener_implements( |
|
|
|
ddl, "org.qemu.Display1.Listener.Unix.ScanoutDMABUF2")) { |
|
|
|
return; |
|
|
|
} |
|
|
|
ddl->scanout_dmabuf_v2_proxy = |
|
|
|
qemu_dbus_display1_listener_unix_scanout_dmabuf2_proxy_new_sync( |
|
|
|
ddl->conn, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, |
|
|
|
"/org/qemu/Display1/Listener", NULL, &err); |
|
|
|
if (!ddl->scanout_dmabuf_v2_proxy) { |
|
|
|
g_debug("Failed to setup Unix scanout dmabuf v2 proxy: %s", err->message); |
|
|
|
return; |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
static GDBusMessage * |
|
|
|
dbus_filter(GDBusConnection *connection, |
|
|
|
GDBusMessage *message, |
|
|
|
@ -1162,6 +1261,7 @@ dbus_display_listener_new(const char *bus_name, |
|
|
|
dbus_display_listener_setup_shared_map(ddl); |
|
|
|
trace_dbus_can_share_map(ddl->can_share_map); |
|
|
|
dbus_display_listener_setup_d3d11(ddl); |
|
|
|
dbus_display_listener_setup_scanout_dmabuf_v2(ddl); |
|
|
|
|
|
|
|
con = qemu_console_lookup_by_index(dbus_display_console_get_index(console)); |
|
|
|
assert(con); |
|
|
|
|