mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 23:33:54 -06:00
ui/dbus: change dbus ScanoutDMABUF interface
To handle multi plane. v3: * rename interface * add x/y/backing_width/backing_height arg v2: * use new dmabuf API and check length Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Qiang Yu <yuq825@gmail.com> Message-ID: <20250327025848.46962-6-yuq825@gmail.com> [ Fix style ] Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
0e15d0b927
commit
10aaad0edc
2 changed files with 152 additions and 7 deletions
|
@ -614,6 +614,51 @@
|
||||||
</method>
|
</method>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
org.qemu.Display1.Listener.Unix.ScanoutDMABUF2:
|
||||||
|
|
||||||
|
This optional client-side interface can complement
|
||||||
|
org.qemu.Display1.Listener on ``/org/qemu/Display1/Listener`` for
|
||||||
|
Unix-specific DMABUF scanout setup which support multi plane.
|
||||||
|
-->
|
||||||
|
<?if $(env.HOST_OS) != windows?>
|
||||||
|
<interface name="org.qemu.Display1.Listener.Unix.ScanoutDMABUF2">
|
||||||
|
<!--
|
||||||
|
ScanoutDMABUF2:
|
||||||
|
@dmabuf: DMABUF file descriptor of each plane.
|
||||||
|
@x: display x offset, in pixels
|
||||||
|
@y: display y offset, in pixels
|
||||||
|
@width: display width, in pixels.
|
||||||
|
@height: display height, in pixels.
|
||||||
|
@offset: offset of each plane, in bytes.
|
||||||
|
@stride: stride of each plane, in bytes.
|
||||||
|
@num_planes: plane number.
|
||||||
|
@fourcc: DMABUF fourcc.
|
||||||
|
@backing_width: backing framebuffer width, in pixels
|
||||||
|
@backing_height: backing framebuffer height, in pixels
|
||||||
|
@modifier: DMABUF modifier.
|
||||||
|
@y0_top: whether Y position 0 is the top or not.
|
||||||
|
|
||||||
|
Resize and update the display content with DMABUF.
|
||||||
|
-->
|
||||||
|
<method name="ScanoutDMABUF2">
|
||||||
|
<arg type="ah" name="dmabuf" direction="in"/>
|
||||||
|
<arg type="u" name="x" direction="in"/>
|
||||||
|
<arg type="u" name="y" direction="in"/>
|
||||||
|
<arg type="u" name="width" direction="in"/>
|
||||||
|
<arg type="u" name="height" direction="in"/>
|
||||||
|
<arg type="au" name="offset" direction="in"/>
|
||||||
|
<arg type="au" name="stride" direction="in"/>
|
||||||
|
<arg type="u" name="num_planes" direction="in"/>
|
||||||
|
<arg type="u" name="fourcc" direction="in"/>
|
||||||
|
<arg type="u" name="backing_width" direction="in"/>
|
||||||
|
<arg type="u" name="backing_height" direction="in"/>
|
||||||
|
<arg type="t" name="modifier" direction="in"/>
|
||||||
|
<arg type="b" name="y0_top" direction="in"/>
|
||||||
|
</method>
|
||||||
|
</interface>
|
||||||
|
<?endif?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
org.qemu.Display1.Clipboard:
|
org.qemu.Display1.Clipboard:
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,7 @@ struct _DBusDisplayListener {
|
||||||
#endif
|
#endif
|
||||||
#else /* !WIN32 */
|
#else /* !WIN32 */
|
||||||
QemuDBusDisplay1ListenerUnixMap *map_proxy;
|
QemuDBusDisplay1ListenerUnixMap *map_proxy;
|
||||||
|
QemuDBusDisplay1ListenerUnixScanoutDMABUF2 *scanout_dmabuf_v2_proxy;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
guint dbus_filter;
|
guint dbus_filter;
|
||||||
|
@ -288,10 +289,9 @@ static void dbus_call_update_gl(DisplayChangeListener *dcl,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_GBM
|
#ifdef CONFIG_GBM
|
||||||
static void dbus_scanout_dmabuf(DisplayChangeListener *dcl,
|
static void dbus_scanout_dmabuf_v1(DBusDisplayListener *ddl,
|
||||||
QemuDmaBuf *dmabuf)
|
QemuDmaBuf *dmabuf)
|
||||||
{
|
{
|
||||||
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
|
|
||||||
g_autoptr(GError) err = NULL;
|
g_autoptr(GError) err = NULL;
|
||||||
g_autoptr(GUnixFDList) fd_list = NULL;
|
g_autoptr(GUnixFDList) fd_list = NULL;
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -322,6 +322,87 @@ static void dbus_scanout_dmabuf(DisplayChangeListener *dcl,
|
||||||
y0_top, G_DBUS_CALL_FLAGS_NONE,
|
y0_top, G_DBUS_CALL_FLAGS_NONE,
|
||||||
-1, fd_list, NULL, NULL, NULL);
|
-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 /* GBM */
|
||||||
#endif /* OPENGL */
|
#endif /* OPENGL */
|
||||||
|
|
||||||
|
@ -514,10 +595,6 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
|
||||||
error_report("%s: failed to export dmabuf for texture", __func__);
|
error_report("%s: failed to export dmabuf for texture", __func__);
|
||||||
return;
|
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,
|
dmabuf = qemu_dmabuf_new(w, h, offset, stride, x, y, backing_width,
|
||||||
backing_height, fourcc, modifier, fd, num_planes,
|
backing_height, fourcc, modifier, fd, num_planes,
|
||||||
false, backing_y_0_top);
|
false, backing_y_0_top);
|
||||||
|
@ -886,6 +963,8 @@ dbus_display_listener_dispose(GObject *object)
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
egl_fb_destroy(&ddl->fb);
|
egl_fb_destroy(&ddl->fb);
|
||||||
#endif
|
#endif
|
||||||
|
#else /* !WIN32 */
|
||||||
|
g_clear_object(&ddl->scanout_dmabuf_v2_proxy);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
G_OBJECT_CLASS(dbus_display_listener_parent_class)->dispose(object);
|
G_OBJECT_CLASS(dbus_display_listener_parent_class)->dispose(object);
|
||||||
|
@ -1074,6 +1153,26 @@ dbus_display_listener_setup_shared_map(DBusDisplayListener *ddl)
|
||||||
#endif
|
#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 *
|
static GDBusMessage *
|
||||||
dbus_filter(GDBusConnection *connection,
|
dbus_filter(GDBusConnection *connection,
|
||||||
GDBusMessage *message,
|
GDBusMessage *message,
|
||||||
|
@ -1162,6 +1261,7 @@ dbus_display_listener_new(const char *bus_name,
|
||||||
dbus_display_listener_setup_shared_map(ddl);
|
dbus_display_listener_setup_shared_map(ddl);
|
||||||
trace_dbus_can_share_map(ddl->can_share_map);
|
trace_dbus_can_share_map(ddl->can_share_map);
|
||||||
dbus_display_listener_setup_d3d11(ddl);
|
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));
|
con = qemu_console_lookup_by_index(dbus_display_console_get_index(console));
|
||||||
assert(con);
|
assert(con);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue