virgl/drm: add resource create blob function

A blob resource is a container for:
  - VIRTGPU_BLOB_MEM_GUEST: a guest memory allocation
    (referred to as a "guest-only blob resource")

  - VIRTGPU_BLOB_MEM_HOST3D: a host3d memory allocation
    (referred to as a "host-only blob resource")

  - VIRTGPU_BLOB_MEM_HOST3D_GUEST: a guest + host3d memory allocation
    (referred to as a "default blob resource").

Blob resources can be used to implement new features and fix shortcomings
with the current resource create path.  The subsequent patches how
blob resources may be leveraged to implement GL_ARB_buffer_storage
and get GL4.5.

Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4821>
This commit is contained in:
Gurchetan Singh 2020-04-28 17:13:46 -07:00
parent e01ec6ed2d
commit cd31f46f08
2 changed files with 76 additions and 0 deletions

View File

@ -39,6 +39,7 @@
#include "frontend/drm_driver.h"
#include "virgl/virgl_screen.h"
#include "virgl/virgl_public.h"
#include "virtio-gpu/virgl_protocol.h"
#include <xf86drm.h>
#include <libsync.h>
@ -144,6 +145,78 @@ static void virgl_drm_resource_reference(struct virgl_winsys *qws,
*dres = sres;
}
static struct virgl_hw_res *
virgl_drm_winsys_resource_create_blob(struct virgl_winsys *qws,
enum pipe_texture_target target,
uint32_t format,
uint32_t bind,
uint32_t width,
uint32_t height,
uint32_t depth,
uint32_t array_size,
uint32_t last_level,
uint32_t nr_samples,
uint32_t flags,
uint32_t size)
{
int ret;
int32_t blob_id;
uint32_t cmd[VIRGL_PIPE_RES_CREATE_SIZE + 1] = { 0 };
struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws);
struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
struct virgl_hw_res *res;
res = CALLOC_STRUCT(virgl_hw_res);
if (!res)
return NULL;
/* Make sure blob is page aligned. */
if (flags & (VIRGL_RESOURCE_FLAG_MAP_PERSISTENT |
VIRGL_RESOURCE_FLAG_MAP_COHERENT)) {
width = ALIGN(width, getpagesize());
size = ALIGN(width, getpagesize());
}
blob_id = p_atomic_inc_return(&qdws->blob_id);
cmd[0] = VIRGL_CMD0(VIRGL_CCMD_PIPE_RESOURCE_CREATE, 0, VIRGL_PIPE_RES_CREATE_SIZE);
cmd[VIRGL_PIPE_RES_CREATE_FORMAT] = format;
cmd[VIRGL_PIPE_RES_CREATE_BIND] = bind;
cmd[VIRGL_PIPE_RES_CREATE_TARGET] = target;
cmd[VIRGL_PIPE_RES_CREATE_WIDTH] = width;
cmd[VIRGL_PIPE_RES_CREATE_HEIGHT] = height;
cmd[VIRGL_PIPE_RES_CREATE_DEPTH] = depth;
cmd[VIRGL_PIPE_RES_CREATE_ARRAY_SIZE] = array_size;
cmd[VIRGL_PIPE_RES_CREATE_LAST_LEVEL] = last_level;
cmd[VIRGL_PIPE_RES_CREATE_NR_SAMPLES] = nr_samples;
cmd[VIRGL_PIPE_RES_CREATE_FLAGS] = flags;
cmd[VIRGL_PIPE_RES_CREATE_BLOB_ID] = blob_id;
drm_rc_blob.cmd = (unsigned long)(void *)&cmd;
drm_rc_blob.cmd_size = 4 * (VIRGL_PIPE_RES_CREATE_SIZE + 1);
drm_rc_blob.size = size;
drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST3D;
drm_rc_blob.blob_flags = VIRTGPU_BLOB_FLAG_USE_MAPPABLE;
drm_rc_blob.blob_id = (uint64_t) blob_id;
ret = drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob);
if (ret != 0) {
FREE(res);
return NULL;
}
res->bind = bind;
res->res_handle = drm_rc_blob.res_handle;
res->bo_handle = drm_rc_blob.bo_handle;
res->size = size;
res->flags = flags;
pipe_reference_init(&res->reference, 1);
p_atomic_set(&res->external, false);
p_atomic_set(&res->num_cs_references, 0);
virgl_resource_cache_entry_init(&res->cache_entry, size, bind, format,
flags);
return res;
}
static struct virgl_hw_res *
virgl_drm_winsys_resource_create(struct virgl_winsys *qws,
enum pipe_texture_target target,
@ -969,6 +1042,8 @@ virgl_drm_winsys_create(int drmFD)
qdws);
(void) mtx_init(&qdws->mutex, mtx_plain);
(void) mtx_init(&qdws->bo_handles_mutex, mtx_plain);
p_atomic_set(&qdws->blob_id, 0);
qdws->bo_handles = util_hash_table_create_ptr_keys();
qdws->bo_names = util_hash_table_create_ptr_keys();
qdws->base.destroy = virgl_drm_winsys_destroy;

View File

@ -85,6 +85,7 @@ struct virgl_drm_winsys
struct virgl_resource_cache cache;
mtx_t mutex;
int32_t blob_id;
struct hash_table *bo_handles;
struct hash_table *bo_names;
mtx_t bo_handles_mutex;