qemu/include/hw/virtio/virtio-gpu.h
<<
>>
Prefs
   1/*
   2 * Virtio GPU Device
   3 *
   4 * Copyright Red Hat, Inc. 2013-2014
   5 *
   6 * Authors:
   7 *     Dave Airlie <airlied@redhat.com>
   8 *     Gerd Hoffmann <kraxel@redhat.com>
   9 *
  10 * This work is licensed under the terms of the GNU GPL, version 2.
  11 * See the COPYING file in the top-level directory.
  12 */
  13
  14#ifndef HW_VIRTIO_GPU_H
  15#define HW_VIRTIO_GPU_H
  16
  17#include "qemu/queue.h"
  18#include "ui/qemu-pixman.h"
  19#include "ui/console.h"
  20#include "hw/virtio/virtio.h"
  21#include "qemu/log.h"
  22#include "sysemu/vhost-user-backend.h"
  23
  24#include "standard-headers/linux/virtio_gpu.h"
  25#include "qom/object.h"
  26
  27#define TYPE_VIRTIO_GPU_BASE "virtio-gpu-base"
  28OBJECT_DECLARE_TYPE(VirtIOGPUBase, VirtIOGPUBaseClass,
  29                    VIRTIO_GPU_BASE)
  30
  31#define TYPE_VIRTIO_GPU "virtio-gpu-device"
  32OBJECT_DECLARE_TYPE(VirtIOGPU, VirtIOGPUClass, VIRTIO_GPU)
  33
  34#define TYPE_VIRTIO_GPU_GL "virtio-gpu-gl-device"
  35OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPUGL, VIRTIO_GPU_GL)
  36
  37#define TYPE_VHOST_USER_GPU "vhost-user-gpu"
  38OBJECT_DECLARE_SIMPLE_TYPE(VhostUserGPU, VHOST_USER_GPU)
  39
  40#define VIRTIO_ID_GPU 16
  41
  42struct virtio_gpu_simple_resource {
  43    uint32_t resource_id;
  44    uint32_t width;
  45    uint32_t height;
  46    uint32_t format;
  47    uint64_t *addrs;
  48    struct iovec *iov;
  49    unsigned int iov_cnt;
  50    uint32_t scanout_bitmask;
  51    pixman_image_t *image;
  52    uint64_t hostmem;
  53
  54    uint64_t blob_size;
  55    void *blob;
  56    int dmabuf_fd;
  57    uint8_t *remapped;
  58
  59    QTAILQ_ENTRY(virtio_gpu_simple_resource) next;
  60};
  61
  62struct virtio_gpu_framebuffer {
  63    pixman_format_code_t format;
  64    uint32_t bytes_pp;
  65    uint32_t width, height;
  66    uint32_t stride;
  67    uint32_t offset;
  68};
  69
  70struct virtio_gpu_scanout {
  71    QemuConsole *con;
  72    DisplaySurface *ds;
  73    uint32_t width, height;
  74    int x, y;
  75    int invalidate;
  76    uint32_t resource_id;
  77    struct virtio_gpu_update_cursor cursor;
  78    QEMUCursor *current_cursor;
  79};
  80
  81struct virtio_gpu_requested_state {
  82    uint16_t width_mm, height_mm;
  83    uint32_t width, height;
  84    int x, y;
  85};
  86
  87enum virtio_gpu_base_conf_flags {
  88    VIRTIO_GPU_FLAG_VIRGL_ENABLED = 1,
  89    VIRTIO_GPU_FLAG_STATS_ENABLED,
  90    VIRTIO_GPU_FLAG_EDID_ENABLED,
  91    VIRTIO_GPU_FLAG_DMABUF_ENABLED,
  92    VIRTIO_GPU_FLAG_BLOB_ENABLED,
  93};
  94
  95#define virtio_gpu_virgl_enabled(_cfg) \
  96    (_cfg.flags & (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED))
  97#define virtio_gpu_stats_enabled(_cfg) \
  98    (_cfg.flags & (1 << VIRTIO_GPU_FLAG_STATS_ENABLED))
  99#define virtio_gpu_edid_enabled(_cfg) \
 100    (_cfg.flags & (1 << VIRTIO_GPU_FLAG_EDID_ENABLED))
 101#define virtio_gpu_dmabuf_enabled(_cfg) \
 102    (_cfg.flags & (1 << VIRTIO_GPU_FLAG_DMABUF_ENABLED))
 103#define virtio_gpu_blob_enabled(_cfg) \
 104    (_cfg.flags & (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED))
 105
 106struct virtio_gpu_base_conf {
 107    uint32_t max_outputs;
 108    uint32_t flags;
 109    uint32_t xres;
 110    uint32_t yres;
 111};
 112
 113struct virtio_gpu_ctrl_command {
 114    VirtQueueElement elem;
 115    VirtQueue *vq;
 116    struct virtio_gpu_ctrl_hdr cmd_hdr;
 117    uint32_t error;
 118    bool finished;
 119    QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
 120};
 121
 122struct VirtIOGPUBase {
 123    VirtIODevice parent_obj;
 124
 125    Error *migration_blocker;
 126
 127    struct virtio_gpu_base_conf conf;
 128    struct virtio_gpu_config virtio_config;
 129    const GraphicHwOps *hw_ops;
 130
 131    int renderer_blocked;
 132    int enable;
 133
 134    struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
 135
 136    int enabled_output_bitmask;
 137    struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS];
 138};
 139
 140struct VirtIOGPUBaseClass {
 141    VirtioDeviceClass parent;
 142
 143    void (*gl_flushed)(VirtIOGPUBase *g);
 144};
 145
 146#define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf)                       \
 147    DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1),    \
 148    DEFINE_PROP_BIT("edid", _state, _conf.flags, \
 149                    VIRTIO_GPU_FLAG_EDID_ENABLED, true), \
 150    DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \
 151    DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)
 152
 153typedef struct VGPUDMABuf {
 154    QemuDmaBuf buf;
 155    uint32_t scanout_id;
 156    QTAILQ_ENTRY(VGPUDMABuf) next;
 157} VGPUDMABuf;
 158
 159struct VirtIOGPU {
 160    VirtIOGPUBase parent_obj;
 161
 162    uint64_t conf_max_hostmem;
 163
 164    VirtQueue *ctrl_vq;
 165    VirtQueue *cursor_vq;
 166
 167    QEMUBH *ctrl_bh;
 168    QEMUBH *cursor_bh;
 169
 170    QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
 171    QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq;
 172    QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
 173
 174    uint64_t hostmem;
 175
 176    bool processing_cmdq;
 177    QEMUTimer *fence_poll;
 178    QEMUTimer *print_stats;
 179
 180    uint32_t inflight;
 181    struct {
 182        uint32_t max_inflight;
 183        uint32_t requests;
 184        uint32_t req_3d;
 185        uint32_t bytes_3d;
 186    } stats;
 187
 188    struct {
 189        QTAILQ_HEAD(, VGPUDMABuf) bufs;
 190        VGPUDMABuf *primary[VIRTIO_GPU_MAX_SCANOUTS];
 191    } dmabuf;
 192};
 193
 194struct VirtIOGPUClass {
 195    VirtIOGPUBaseClass parent;
 196
 197    void (*handle_ctrl)(VirtIODevice *vdev, VirtQueue *vq);
 198    void (*process_cmd)(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd);
 199    void (*update_cursor_data)(VirtIOGPU *g,
 200                               struct virtio_gpu_scanout *s,
 201                               uint32_t resource_id);
 202};
 203
 204struct VirtIOGPUGL {
 205    struct VirtIOGPU parent_obj;
 206
 207    bool renderer_inited;
 208    bool renderer_reset;
 209};
 210
 211struct VhostUserGPU {
 212    VirtIOGPUBase parent_obj;
 213
 214    VhostUserBackend *vhost;
 215    int vhost_gpu_fd; /* closed by the chardev */
 216    CharBackend vhost_chr;
 217    QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
 218    bool backend_blocked;
 219};
 220
 221#define VIRTIO_GPU_FILL_CMD(out) do {                                   \
 222        size_t s;                                                       \
 223        s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0,          \
 224                       &out, sizeof(out));                              \
 225        if (s != sizeof(out)) {                                         \
 226            qemu_log_mask(LOG_GUEST_ERROR,                              \
 227                          "%s: command size incorrect %zu vs %zu\n",    \
 228                          __func__, s, sizeof(out));                    \
 229            return;                                                     \
 230        }                                                               \
 231    } while (0)
 232
 233/* virtio-gpu-base.c */
 234bool virtio_gpu_base_device_realize(DeviceState *qdev,
 235                                    VirtIOHandleOutput ctrl_cb,
 236                                    VirtIOHandleOutput cursor_cb,
 237                                    Error **errp);
 238void virtio_gpu_base_reset(VirtIOGPUBase *g);
 239void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g,
 240                        struct virtio_gpu_resp_display_info *dpy_info);
 241
 242/* virtio-gpu.c */
 243void virtio_gpu_ctrl_response(VirtIOGPU *g,
 244                              struct virtio_gpu_ctrl_command *cmd,
 245                              struct virtio_gpu_ctrl_hdr *resp,
 246                              size_t resp_len);
 247void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g,
 248                                     struct virtio_gpu_ctrl_command *cmd,
 249                                     enum virtio_gpu_ctrl_type type);
 250void virtio_gpu_get_display_info(VirtIOGPU *g,
 251                                 struct virtio_gpu_ctrl_command *cmd);
 252void virtio_gpu_get_edid(VirtIOGPU *g,
 253                         struct virtio_gpu_ctrl_command *cmd);
 254int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
 255                                  uint32_t nr_entries, uint32_t offset,
 256                                  struct virtio_gpu_ctrl_command *cmd,
 257                                  uint64_t **addr, struct iovec **iov,
 258                                  uint32_t *niov);
 259void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g,
 260                                    struct iovec *iov, uint32_t count);
 261void virtio_gpu_process_cmdq(VirtIOGPU *g);
 262void virtio_gpu_device_realize(DeviceState *qdev, Error **errp);
 263void virtio_gpu_reset(VirtIODevice *vdev);
 264void virtio_gpu_simple_process_cmd(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd);
 265void virtio_gpu_update_cursor_data(VirtIOGPU *g,
 266                                   struct virtio_gpu_scanout *s,
 267                                   uint32_t resource_id);
 268
 269/* virtio-gpu-udmabuf.c */
 270bool virtio_gpu_have_udmabuf(void);
 271void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
 272void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res);
 273int virtio_gpu_update_dmabuf(VirtIOGPU *g,
 274                             uint32_t scanout_id,
 275                             struct virtio_gpu_simple_resource *res,
 276                             struct virtio_gpu_framebuffer *fb,
 277                             struct virtio_gpu_rect *r);
 278
 279/* virtio-gpu-3d.c */
 280void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
 281                                  struct virtio_gpu_ctrl_command *cmd);
 282void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
 283void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
 284void virtio_gpu_virgl_reset(VirtIOGPU *g);
 285int virtio_gpu_virgl_init(VirtIOGPU *g);
 286int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
 287
 288#endif
 289