qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v6 9/9] vfio/display: adding dmabuf support


From: Zhang, Tina
Subject: Re: [Qemu-devel] [PATCH v6 9/9] vfio/display: adding dmabuf support
Date: Thu, 1 Mar 2018 08:59:43 +0000


> -----Original Message-----
> From: intel-gvt-dev [mailto:address@hidden On
> Behalf Of Gerd Hoffmann
> Sent: Wednesday, February 28, 2018 8:31 PM
> To: address@hidden
> Cc: Alex Williamson <address@hidden>; Gerd Hoffmann
> <address@hidden>; address@hidden; Kirti Wankhede
> <address@hidden>; Zhang, Tina <address@hidden>
> Subject: [PATCH v6 9/9] vfio/display: adding dmabuf support
> 
> Wire up dmabuf-based display.
> 
> Signed-off-by: Gerd Hoffmann <address@hidden>
> ---
Please see my comments below.
Tested-by: Tina Zhang <address@hidden>

>  include/hw/vfio/vfio-common.h |  14 ++++
>  hw/vfio/display.c             | 166
> +++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 178 insertions(+), 2 deletions(-)
> 
> diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
> index fc8ae14fb7..994e780d51 100644
> --- a/include/hw/vfio/vfio-common.h
> +++ b/include/hw/vfio/vfio-common.h
> @@ -26,6 +26,7 @@
>  #include "exec/memory.h"
>  #include "qemu/queue.h"
>  #include "qemu/notify.h"
> +#include "ui/console.h"
>  #ifdef CONFIG_LINUX
>  #include <linux/vfio.h>
>  #endif
> @@ -142,12 +143,25 @@ typedef struct VFIOGroup {
>      QLIST_ENTRY(VFIOGroup) container_next;  } VFIOGroup;
> 
> +typedef struct VFIODMABuf {
> +    QemuDmaBuf buf;
> +    uint32_t pos_x, pos_y;
> +    uint32_t hot_x, hot_y;
> +    int dmabuf_id;
> +    QTAILQ_ENTRY(VFIODMABuf) next;
> +} VFIODMABuf;
> +
>  typedef struct VFIODisplay {
>      QemuConsole *con;
>      struct {
>          VFIORegion buffer;
>          DisplaySurface *surface;
>      } region;
> +    struct {
> +        QTAILQ_HEAD(, VFIODMABuf) bufs;
> +        VFIODMABuf *primary;
> +        VFIODMABuf *cursor;
> +    } dmabuf;
>  } VFIODisplay;
> 
>  void vfio_put_base_device(VFIODevice *vbasedev); diff --git
> a/hw/vfio/display.c b/hw/vfio/display.c index f6acbacc79..053d3ab67a 100644
> --- a/hw/vfio/display.c
> +++ b/hw/vfio/display.c
> @@ -19,6 +19,168 @@
>  #include "qapi/error.h"
>  #include "pci.h"
> 
> +#ifndef DRM_PLANE_TYPE_PRIMARY
> +# define DRM_PLANE_TYPE_PRIMARY 1
> +# define DRM_PLANE_TYPE_CURSOR  2
> +#endif
> +
> +static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev,
> +                                           uint32_t plane_type) {
> +    VFIODisplay *dpy = vdev->dpy;
> +    struct vfio_device_gfx_plane_info plane;
> +    VFIODMABuf *dmabuf;
> +    int fd, ret;
> +
> +    memset(&plane, 0, sizeof(plane));
> +    plane.argsz = sizeof(plane);
> +    plane.flags = VFIO_GFX_PLANE_TYPE_DMABUF;
> +    plane.drm_plane_type = plane_type;
> +    ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_QUERY_GFX_PLANE, &plane);
> +    if (ret < 0) {
> +        return NULL;
> +    }
> +    if (!plane.drm_format || !plane.size) {
> +        return NULL;
> +    }
> +
> +    QTAILQ_FOREACH(dmabuf, &dpy->dmabuf.bufs, next) {
> +        if (dmabuf->dmabuf_id == plane.dmabuf_id) {
> +            /* found in list, move to head, return it */
> +            QTAILQ_REMOVE(&dpy->dmabuf.bufs, dmabuf, next);
> +            QTAILQ_INSERT_HEAD(&dpy->dmabuf.bufs, dmabuf, next);
> +            if (plane_type == DRM_PLANE_TYPE_CURSOR) {
> +                dmabuf->pos_x      = plane.x_pos;
> +                dmabuf->pos_y      = plane.y_pos;
Better also update plane.x_hot and plane.y_hot here.
The "pos_x", "pos_y", "hot_x" and "hot_y" fields would be updated with each 
time VFIO_DEVICE_QUERY_GFX_PLANE is invoked, although dmabuf object may be 
reused.

BR,
Tina
> +            }
> +            return dmabuf;
> +        }
> +    }
> +
> +    fd = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_GFX_DMABUF,
> &plane.dmabuf_id);
> +    if (fd < 0) {
> +        return NULL;
> +    }
> +
> +    dmabuf = g_new0(VFIODMABuf, 1);
> +    dmabuf->dmabuf_id  = plane.dmabuf_id;
> +    dmabuf->buf.width  = plane.width;
> +    dmabuf->buf.height = plane.height;
> +    dmabuf->buf.stride = plane.stride;
> +    dmabuf->buf.fourcc = plane.drm_format;
> +    dmabuf->buf.fd     = fd;
> +    if (plane_type == DRM_PLANE_TYPE_CURSOR) {
> +        dmabuf->pos_x      = plane.x_pos;
> +        dmabuf->pos_y      = plane.y_pos;
> +        dmabuf->hot_x      = plane.x_hot;
> +        dmabuf->hot_y      = plane.y_hot;
> +    }
> +
> +    QTAILQ_INSERT_HEAD(&dpy->dmabuf.bufs, dmabuf, next);
> +    return dmabuf;
> +}
> +
> +static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf
> +*dmabuf) {
> +    QTAILQ_REMOVE(&dpy->dmabuf.bufs, dmabuf, next);
> +    dpy_gl_release_dmabuf(dpy->con, &dmabuf->buf);
> +    close(dmabuf->buf.fd);
> +    g_free(dmabuf);
> +}
> +
> +static void vfio_display_free_dmabufs(VFIOPCIDevice *vdev) {
> +    VFIODisplay *dpy = vdev->dpy;
> +    VFIODMABuf *dmabuf, *tmp;
> +    uint32_t keep = 5;
> +
> +    QTAILQ_FOREACH_SAFE(dmabuf, &dpy->dmabuf.bufs, next, tmp) {
> +        if (keep > 0) {
> +            keep--;
> +            continue;
> +        }
> +        assert(dmabuf != dpy->dmabuf.primary);
> +        vfio_display_free_one_dmabuf(dpy, dmabuf);
> +    }
> +}
> +
> +static void vfio_display_dmabuf_update(void *opaque) {
> +    VFIOPCIDevice *vdev = opaque;
> +    VFIODisplay *dpy = vdev->dpy;
> +    VFIODMABuf *primary, *cursor;
> +    bool free_bufs = false;
> +
> +    primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY);
> +    if (primary == NULL) {
> +        return;
> +    }
> +
> +    if (dpy->dmabuf.primary != primary) {
> +        dpy->dmabuf.primary = primary;
> +        qemu_console_resize(dpy->con,
> +                            primary->buf.width, primary->buf.height);
> +        dpy_gl_scanout_dmabuf(dpy->con, &primary->buf);
> +        free_bufs = true;
> +    }
> +
> +    cursor = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_CURSOR);
> +    if (dpy->dmabuf.cursor != cursor) {
> +        dpy->dmabuf.cursor = cursor;
> +        if (cursor) {
> +            bool have_hot = (cursor->hot_x != 0xffffffff &&
> +                             cursor->hot_y != 0xffffffff);
> +            dpy_gl_cursor_dmabuf(dpy->con, &cursor->buf, have_hot,
> +                                 cursor->hot_x, cursor->hot_y);
> +        } else {
> +            dpy_gl_cursor_dmabuf(dpy->con, NULL, false, 0, 0);
> +        }
> +        free_bufs = true;
> +    }
> +    if (cursor != NULL) {
> +        dpy_gl_cursor_position(dpy->con,
> +                               cursor->pos_x,
> +                               cursor->pos_y);
> +    }
> +
> +    dpy_gl_update(dpy->con, 0, 0, primary->buf.width,
> + primary->buf.height);
> +
> +    if (free_bufs) {
> +        vfio_display_free_dmabufs(vdev);
> +    }
> +}
> +
> +static const GraphicHwOps vfio_display_dmabuf_ops = {
> +    .gfx_update = vfio_display_dmabuf_update, };
> +
> +static int vfio_display_dmabuf_init(VFIOPCIDevice *vdev, Error **errp)
> +{
> +    if (!display_opengl) {
> +        error_setg(errp, "vfio-display-dmabuf: opengl not available");
> +        return -1;
> +    }
> +
> +    vdev->dpy = g_new0(VFIODisplay, 1);
> +    vdev->dpy->con = graphic_console_init(DEVICE(vdev), 0,
> +                                          &vfio_display_dmabuf_ops,
> +                                          vdev);
> +    return 0;
> +}
> +
> +static void vfio_display_dmabuf_exit(VFIODisplay *dpy) {
> +    VFIODMABuf *dmabuf;
> +
> +    if (QTAILQ_EMPTY(&dpy->dmabuf.bufs)) {
> +        return;
> +    }
> +
> +    while ((dmabuf = QTAILQ_FIRST(&dpy->dmabuf.bufs)) != NULL) {
> +        vfio_display_free_one_dmabuf(dpy, dmabuf);
> +    }
> +}
> +
>  /* ---------------------------------------------------------------------- */
> 
>  static void vfio_display_region_update(void *opaque) @@ -136,8 +298,7 @@
> int vfio_display_probe(VFIOPCIDevice *vdev, Error **errp)
>      probe.flags = VFIO_GFX_PLANE_TYPE_PROBE |
> VFIO_GFX_PLANE_TYPE_DMABUF;
>      ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_QUERY_GFX_PLANE, &probe);
>      if (ret == 0) {
> -        error_setg(errp, "vfio-display: dmabuf support not implemented yet");
> -        return -1;
> +        return vfio_display_dmabuf_init(vdev, errp);
>      }
> 
>      memset(&probe, 0, sizeof(probe));
> @@ -163,6 +324,7 @@ void vfio_display_finalize(VFIOPCIDevice *vdev)
>          return;
> 
>      graphic_console_close(vdev->dpy->con);
> +    vfio_display_dmabuf_exit(vdev->dpy);
>      vfio_display_region_exit(vdev->dpy);
>      g_free(vdev->dpy);
>  }
> --
> 2.9.3
> 
> _______________________________________________
> intel-gvt-dev mailing list
> address@hidden
> https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev

reply via email to

[Prev in Thread] Current Thread [Next in Thread]