| /* |
| * Copyright © 2023 Google, Inc. |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| /* A simple helper layer for virtgpu drm native context, which also |
| * abstracted the differences between vtest (communicating via socket |
| * with vtest server) vs virtgpu (communicating via drm/virtio driver |
| * in the guest). |
| */ |
| |
| #ifndef __VDRM_H__ |
| #define __VDRM_H__ |
| |
| #include <stdint.h> |
| |
| #include "util/simple_mtx.h" |
| |
| #include "virglrenderer_hw.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| struct vdrm_device; |
| struct vdrm_execbuf_params; |
| |
| struct vdrm_device_funcs { |
| /* Note flush_locked and execbuf_locked are similar, and on top of virtgpu |
| * guest kernel driver are basically the same. But with vtest, only cmds |
| * that result in host kernel cmd submission can take and/or return fence |
| * and/or syncobj fd's. |
| */ |
| int (*execbuf_locked)(struct vdrm_device *vdev, struct vdrm_execbuf_params *p, |
| void *command, unsigned size); |
| int (*flush_locked)(struct vdrm_device *vdev, uintptr_t *fencep); |
| |
| void (*wait_fence)(struct vdrm_device *vdev, uintptr_t fence); |
| |
| uint32_t (*dmabuf_to_handle)(struct vdrm_device *vdev, int fd); |
| uint32_t (*handle_to_res_id)(struct vdrm_device *vdev, uint32_t handle); |
| |
| uint32_t (*bo_create)(struct vdrm_device *vdev, size_t size, uint32_t blob_flags, |
| uint64_t blob_id, struct vdrm_ccmd_req *req); |
| int (*bo_wait)(struct vdrm_device *vdev, uint32_t handle); |
| void *(*bo_map)(struct vdrm_device *vdev, uint32_t handle, size_t size, void *placed_addr); |
| int (*bo_export_dmabuf)(struct vdrm_device *vdev, uint32_t handle); |
| void (*bo_close)(struct vdrm_device *vdev, uint32_t handle); |
| |
| void (*close)(struct vdrm_device *vdev); |
| }; |
| |
| struct vdrm_device { |
| const struct vdrm_device_funcs *funcs; |
| |
| struct virgl_renderer_capset_drm caps; |
| struct vdrm_shmem *shmem; |
| uint8_t *rsp_mem; |
| uint32_t rsp_mem_len; |
| uint32_t next_rsp_off; |
| simple_mtx_t rsp_lock; |
| simple_mtx_t eb_lock; |
| |
| uint32_t next_seqno; |
| |
| /* |
| * Buffering for requests to host: |
| */ |
| uint32_t reqbuf_len; |
| uint32_t reqbuf_cnt; |
| uint8_t reqbuf[0x4000]; |
| }; |
| |
| struct vdrm_device *vdrm_device_connect(int fd, uint32_t context_type); |
| void vdrm_device_close(struct vdrm_device *vdev); |
| |
| void * vdrm_alloc_rsp(struct vdrm_device *vdev, struct vdrm_ccmd_req *req, uint32_t sz); |
| int vdrm_send_req(struct vdrm_device *vdev, struct vdrm_ccmd_req *req, bool sync); |
| int vdrm_flush(struct vdrm_device *vdev); |
| |
| struct vdrm_execbuf_params { |
| int ring_idx; |
| |
| struct vdrm_ccmd_req *req; /* Note, must be host kernel cmd submit */ |
| |
| uint32_t *handles; |
| uint32_t num_handles; |
| |
| struct drm_virtgpu_execbuffer_syncobj *in_syncobjs; |
| struct drm_virtgpu_execbuffer_syncobj *out_syncobjs; |
| |
| bool has_in_fence_fd : 1; |
| bool needs_out_fence_fd : 1; |
| |
| int fence_fd; /* in/out fence */ |
| |
| uint32_t num_in_syncobjs; |
| uint32_t num_out_syncobjs; |
| }; |
| |
| /** |
| * Note, must be a host cmd submission, which specified in/out fence/syncobj |
| * can be passed to. In the vtest case, we can't get fences/syncobjs for |
| * other host cmds. |
| */ |
| int vdrm_execbuf(struct vdrm_device *vdev, struct vdrm_execbuf_params *p); |
| |
| void vdrm_host_sync(struct vdrm_device *vdev, const struct vdrm_ccmd_req *req); |
| |
| /** |
| * Import dmabuf fd returning a GEM handle |
| */ |
| static inline uint32_t |
| vdrm_dmabuf_to_handle(struct vdrm_device *vdev, int fd) |
| { |
| return vdev->funcs->dmabuf_to_handle(vdev, fd); |
| } |
| |
| static inline uint32_t |
| vdrm_handle_to_res_id(struct vdrm_device *vdev, uint32_t handle) |
| { |
| return vdev->funcs->handle_to_res_id(vdev, handle); |
| } |
| |
| uint32_t vdrm_bo_create(struct vdrm_device *vdev, size_t size, |
| uint32_t blob_flags, uint64_t blob_id, |
| struct vdrm_ccmd_req *req); |
| |
| static inline int |
| vdrm_bo_wait(struct vdrm_device *vdev, uint32_t handle) |
| { |
| return vdev->funcs->bo_wait(vdev, handle); |
| } |
| |
| static inline void * |
| vdrm_bo_map(struct vdrm_device *vdev, uint32_t handle, size_t size, void *placed_addr) |
| { |
| return vdev->funcs->bo_map(vdev, handle, size, placed_addr); |
| } |
| |
| static inline int |
| vdrm_bo_export_dmabuf(struct vdrm_device *vdev, uint32_t handle) |
| { |
| return vdev->funcs->bo_export_dmabuf(vdev, handle); |
| } |
| |
| static inline void |
| vdrm_bo_close(struct vdrm_device *vdev, uint32_t handle) |
| { |
| vdev->funcs->bo_close(vdev, handle); |
| } |
| |
| #ifdef __cplusplus |
| } /* end of extern "C" */ |
| #endif |
| |
| #endif /* __VDRM_H__ */ |