2 * Virtio vhost-user GPU Device
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
10 #include "qemu/osdep.h"
14 mem_alloc_bo(struct vugbm_buffer
*buf
)
16 buf
->mmap
= g_malloc(buf
->width
* buf
->height
* 4);
17 buf
->stride
= buf
->width
* 4;
22 mem_free_bo(struct vugbm_buffer
*buf
)
28 mem_map_bo(struct vugbm_buffer
*buf
)
30 return buf
->mmap
!= NULL
;
34 mem_unmap_bo(struct vugbm_buffer
*buf
)
39 mem_device_destroy(struct vugbm_device
*dev
)
44 struct udmabuf_create
{
51 #define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create)
54 udmabuf_get_size(struct vugbm_buffer
*buf
)
56 return ROUND_UP(buf
->width
* buf
->height
* 4, qemu_real_host_page_size
);
60 udmabuf_alloc_bo(struct vugbm_buffer
*buf
)
64 buf
->memfd
= memfd_create("udmabuf-bo", MFD_ALLOW_SEALING
);
69 ret
= ftruncate(buf
->memfd
, udmabuf_get_size(buf
));
75 ret
= fcntl(buf
->memfd
, F_ADD_SEALS
, F_SEAL_SHRINK
);
81 buf
->stride
= buf
->width
* 4;
87 udmabuf_free_bo(struct vugbm_buffer
*buf
)
93 udmabuf_map_bo(struct vugbm_buffer
*buf
)
95 buf
->mmap
= mmap(NULL
, udmabuf_get_size(buf
),
96 PROT_READ
| PROT_WRITE
, MAP_SHARED
, buf
->memfd
, 0);
97 if (buf
->mmap
== MAP_FAILED
) {
105 udmabuf_get_fd(struct vugbm_buffer
*buf
, int *fd
)
107 struct udmabuf_create create
= {
110 .size
= udmabuf_get_size(buf
),
113 *fd
= ioctl(buf
->dev
->fd
, UDMABUF_CREATE
, &create
);
119 udmabuf_unmap_bo(struct vugbm_buffer
*buf
)
121 munmap(buf
->mmap
, udmabuf_get_size(buf
));
125 udmabuf_device_destroy(struct vugbm_device
*dev
)
133 alloc_bo(struct vugbm_buffer
*buf
)
135 struct gbm_device
*dev
= buf
->dev
->dev
;
139 buf
->bo
= gbm_bo_create(dev
, buf
->width
, buf
->height
,
141 GBM_BO_USE_RENDERING
| GBM_BO_USE_LINEAR
);
144 buf
->stride
= gbm_bo_get_stride(buf
->bo
);
152 free_bo(struct vugbm_buffer
*buf
)
154 gbm_bo_destroy(buf
->bo
);
158 map_bo(struct vugbm_buffer
*buf
)
162 buf
->mmap
= gbm_bo_map(buf
->bo
, 0, 0, buf
->width
, buf
->height
,
163 GBM_BO_TRANSFER_READ_WRITE
, &stride
,
166 assert(stride
== buf
->stride
);
168 return buf
->mmap
!= NULL
;
172 unmap_bo(struct vugbm_buffer
*buf
)
174 gbm_bo_unmap(buf
->bo
, buf
->mmap_data
);
178 get_fd(struct vugbm_buffer
*buf
, int *fd
)
180 *fd
= gbm_bo_get_fd(buf
->bo
);
186 device_destroy(struct vugbm_device
*dev
)
188 gbm_device_destroy(dev
->dev
);
193 vugbm_device_destroy(struct vugbm_device
*dev
)
199 dev
->device_destroy(dev
);
203 vugbm_device_init(struct vugbm_device
*dev
, int fd
)
208 dev
->dev
= gbm_create_device(fd
);
215 else if (dev
->dev
!= NULL
) {
216 dev
->alloc_bo
= alloc_bo
;
217 dev
->free_bo
= free_bo
;
218 dev
->get_fd
= get_fd
;
219 dev
->map_bo
= map_bo
;
220 dev
->unmap_bo
= unmap_bo
;
221 dev
->device_destroy
= device_destroy
;
225 else if (g_file_test("/dev/udmabuf", G_FILE_TEST_EXISTS
)) {
226 dev
->fd
= open("/dev/udmabuf", O_RDWR
);
230 g_debug("Using experimental udmabuf backend");
231 dev
->alloc_bo
= udmabuf_alloc_bo
;
232 dev
->free_bo
= udmabuf_free_bo
;
233 dev
->get_fd
= udmabuf_get_fd
;
234 dev
->map_bo
= udmabuf_map_bo
;
235 dev
->unmap_bo
= udmabuf_unmap_bo
;
236 dev
->device_destroy
= udmabuf_device_destroy
;
240 g_debug("Using mem fallback");
241 dev
->alloc_bo
= mem_alloc_bo
;
242 dev
->free_bo
= mem_free_bo
;
243 dev
->map_bo
= mem_map_bo
;
244 dev
->unmap_bo
= mem_unmap_bo
;
245 dev
->device_destroy
= mem_device_destroy
;
254 vugbm_buffer_map(struct vugbm_buffer
*buf
)
256 struct vugbm_device
*dev
= buf
->dev
;
258 return dev
->map_bo(buf
);
262 vugbm_buffer_unmap(struct vugbm_buffer
*buf
)
264 struct vugbm_device
*dev
= buf
->dev
;
270 vugbm_buffer_can_get_dmabuf_fd(struct vugbm_buffer
*buffer
)
272 if (!buffer
->dev
->get_fd
) {
280 vugbm_buffer_get_dmabuf_fd(struct vugbm_buffer
*buffer
, int *fd
)
282 if (!vugbm_buffer_can_get_dmabuf_fd(buffer
) ||
283 !buffer
->dev
->get_fd(buffer
, fd
)) {
284 g_warning("Failed to get dmabuf");
289 g_warning("error: dmabuf_fd < 0");
297 vugbm_buffer_create(struct vugbm_buffer
*buffer
, struct vugbm_device
*dev
,
298 uint32_t width
, uint32_t height
)
301 buffer
->width
= width
;
302 buffer
->height
= height
;
303 buffer
->format
= GBM_FORMAT_XRGB8888
;
304 buffer
->stride
= 0; /* modified during alloc */
305 if (!dev
->alloc_bo(buffer
)) {
306 g_warning("alloc_bo failed");
310 if (!vugbm_buffer_map(buffer
)) {
311 g_warning("map_bo failed");
318 dev
->free_bo(buffer
);
323 vugbm_buffer_destroy(struct vugbm_buffer
*buffer
)
325 struct vugbm_device
*dev
= buffer
->dev
;
327 vugbm_buffer_unmap(buffer
);
328 dev
->free_bo(buffer
);