summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gallium/winsys/virgl
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2021-07-22 10:50:50 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2021-07-22 10:50:50 +0000
commit9130ec005fbc78a62420643414d8354d0929ca50 (patch)
tree6762777acdd2d4eee17ef87290e80dc7afe2b73d /lib/mesa/src/gallium/winsys/virgl
parentca11beabae33eb59fb981b8adf50b1d47a2a98f0 (diff)
Merge Mesa 21.1.5
Diffstat (limited to 'lib/mesa/src/gallium/winsys/virgl')
-rw-r--r--lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c328
-rw-r--r--lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h38
-rw-r--r--lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c9
-rw-r--r--lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.h2
-rw-r--r--lib/mesa/src/gallium/winsys/virgl/vtest/vtest_protocol.h88
5 files changed, 280 insertions, 185 deletions
diff --git a/lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c b/lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c
index 32dbb4f7d..b49464d1e 100644
--- a/lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c
+++ b/lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c
@@ -29,14 +29,17 @@
#include <sys/stat.h>
#include "os/os_mman.h"
+#include "util/os_file.h"
#include "util/os_time.h"
#include "util/u_memory.h"
#include "util/format/u_format.h"
#include "util/u_hash_table.h"
#include "util/u_inlines.h"
-#include "state_tracker/drm_driver.h"
+#include "util/u_pointer.h"
+#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>
@@ -53,13 +56,14 @@
#define cache_entry_container_res(ptr) \
(struct virgl_hw_res*)((char*)ptr - offsetof(struct virgl_hw_res, cache_entry))
-static inline boolean can_cache_resource_with_bind(uint32_t bind)
+static inline boolean can_cache_resource(uint32_t bind)
{
return bind == VIRGL_BIND_CONSTANT_BUFFER ||
bind == VIRGL_BIND_INDEX_BUFFER ||
bind == VIRGL_BIND_VERTEX_BUFFER ||
bind == VIRGL_BIND_CUSTOM ||
- bind == VIRGL_BIND_STAGING;
+ bind == VIRGL_BIND_STAGING ||
+ bind == VIRGL_BIND_DEPTH_STENCIL;
}
static void virgl_hw_res_destroy(struct virgl_drm_winsys *qdws,
@@ -68,10 +72,20 @@ static void virgl_hw_res_destroy(struct virgl_drm_winsys *qdws,
struct drm_gem_close args;
mtx_lock(&qdws->bo_handles_mutex);
- util_hash_table_remove(qdws->bo_handles,
+
+ /* We intentionally avoid taking the lock in
+ * virgl_drm_resource_reference. Now that the
+ * lock is taken, we need to check the refcount
+ * again. */
+ if (pipe_is_referenced(&res->reference)) {
+ mtx_unlock(&qdws->bo_handles_mutex);
+ return;
+ }
+
+ _mesa_hash_table_remove_key(qdws->bo_handles,
(void *)(uintptr_t)res->bo_handle);
if (res->flink_name)
- util_hash_table_remove(qdws->bo_names,
+ _mesa_hash_table_remove_key(qdws->bo_names,
(void *)(uintptr_t)res->flink_name);
mtx_unlock(&qdws->bo_handles_mutex);
if (res->ptr)
@@ -113,8 +127,8 @@ virgl_drm_winsys_destroy(struct virgl_winsys *qws)
virgl_resource_cache_flush(&qdws->cache);
- util_hash_table_destroy(qdws->bo_handles);
- util_hash_table_destroy(qdws->bo_names);
+ _mesa_hash_table_destroy(qdws->bo_handles, NULL);
+ _mesa_hash_table_destroy(qdws->bo_names, NULL);
mtx_destroy(&qdws->bo_handles_mutex);
mtx_destroy(&qdws->mutex);
@@ -130,7 +144,7 @@ static void virgl_drm_resource_reference(struct virgl_winsys *qws,
if (pipe_reference(&(*dres)->reference, &sres->reference)) {
- if (!can_cache_resource_with_bind(old->bind) ||
+ if (!can_cache_resource(old->bind) ||
p_atomic_read(&old->external)) {
virgl_hw_res_destroy(qdws, old);
} else {
@@ -143,6 +157,79 @@ static void virgl_drm_resource_reference(struct virgl_winsys *qws,
}
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(size, 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;
+ res->maybe_untyped = false;
+ 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,
uint32_t format,
@@ -190,6 +277,8 @@ virgl_drm_winsys_resource_create(struct virgl_winsys *qws,
res->res_handle = createcmd.res_handle;
res->bo_handle = createcmd.bo_handle;
res->size = size;
+ res->target = target;
+ res->maybe_untyped = false;
pipe_reference_init(&res->reference, 1);
p_atomic_set(&res->external, false);
p_atomic_set(&res->num_cs_references, 0);
@@ -200,11 +289,32 @@ virgl_drm_winsys_resource_create(struct virgl_winsys *qws,
*/
p_atomic_set(&res->maybe_busy, for_fencing);
- virgl_resource_cache_entry_init(&res->cache_entry, size, bind, format);
+ virgl_resource_cache_entry_init(&res->cache_entry, size, bind, format, 0);
return res;
}
+/*
+ * Previously, with DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, all host resources had
+ * a guest memory shadow resource with size = stride * bpp. Virglrenderer
+ * would guess the stride implicitly when performing transfer operations, if
+ * the stride wasn't specified. Interestingly, vtest would specify the stride.
+ *
+ * Guessing the stride breaks down with YUV images, which may be imported into
+ * Mesa as 3R8 images. It also doesn't work if an external allocator
+ * (i.e, minigbm) decides to use a stride not equal to stride * bpp. With blob
+ * resources, the size = stride * bpp restriction no longer holds, so use
+ * explicit strides passed into Mesa.
+ */
+static inline bool use_explicit_stride(struct virgl_hw_res *res, uint32_t level,
+ uint32_t depth)
+{
+ return (params[param_resource_blob].value &&
+ res->blob_mem == VIRTGPU_BLOB_MEM_HOST3D_GUEST &&
+ res->target == PIPE_TEXTURE_2D &&
+ level == 0 && depth == 1);
+}
+
static int
virgl_bo_transfer_put(struct virgl_winsys *vws,
struct virgl_hw_res *res,
@@ -227,8 +337,10 @@ virgl_bo_transfer_put(struct virgl_winsys *vws,
tohostcmd.box.d = box->depth;
tohostcmd.offset = buf_offset;
tohostcmd.level = level;
- // tohostcmd.stride = stride;
- // tohostcmd.layer_stride = stride;
+
+ if (use_explicit_stride(res, level, box->depth))
+ tohostcmd.stride = stride;
+
return drmIoctl(vdws->fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &tohostcmd);
}
@@ -248,14 +360,16 @@ virgl_bo_transfer_get(struct virgl_winsys *vws,
fromhostcmd.bo_handle = res->bo_handle;
fromhostcmd.level = level;
fromhostcmd.offset = buf_offset;
- // fromhostcmd.stride = stride;
- // fromhostcmd.layer_stride = layer_stride;
fromhostcmd.box.x = box->x;
fromhostcmd.box.y = box->y;
fromhostcmd.box.z = box->z;
fromhostcmd.box.w = box->width;
fromhostcmd.box.h = box->height;
fromhostcmd.box.d = box->depth;
+
+ if (use_explicit_stride(res, level, box->depth))
+ fromhostcmd.stride = stride;
+
return drmIoctl(vdws->fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &fromhostcmd);
}
@@ -270,19 +384,20 @@ virgl_drm_winsys_resource_cache_create(struct virgl_winsys *qws,
uint32_t array_size,
uint32_t last_level,
uint32_t nr_samples,
+ uint32_t flags,
uint32_t size)
{
struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws);
struct virgl_hw_res *res;
struct virgl_resource_cache_entry *entry;
- if (!can_cache_resource_with_bind(bind))
+ if (!can_cache_resource(bind))
goto alloc;
mtx_lock(&qdws->mutex);
entry = virgl_resource_cache_remove_compatible(&qdws->cache, size,
- bind, format);
+ bind, format, flags);
if (entry) {
res = cache_entry_container_res(entry);
mtx_unlock(&qdws->mutex);
@@ -293,9 +408,17 @@ virgl_drm_winsys_resource_cache_create(struct virgl_winsys *qws,
mtx_unlock(&qdws->mutex);
alloc:
- res = virgl_drm_winsys_resource_create(qws, target, format, bind,
- width, height, depth, array_size,
- last_level, nr_samples, size, false);
+ if (flags & (VIRGL_RESOURCE_FLAG_MAP_PERSISTENT |
+ VIRGL_RESOURCE_FLAG_MAP_COHERENT))
+ res = virgl_drm_winsys_resource_create_blob(qws, target, format, bind,
+ width, height, depth,
+ array_size, last_level,
+ nr_samples, flags, size);
+ else
+ res = virgl_drm_winsys_resource_create(qws, target, format, bind, width,
+ height, depth, array_size,
+ last_level, nr_samples, size,
+ false);
return res;
}
@@ -305,7 +428,8 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws,
uint32_t *plane,
uint32_t *stride,
uint32_t *plane_offset,
- uint64_t *modifier)
+ uint64_t *modifier,
+ uint32_t *blob_mem)
{
struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws);
struct drm_gem_open open_arg = {};
@@ -313,6 +437,10 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws,
struct virgl_hw_res *res = NULL;
uint32_t handle = whandle->handle;
+ if (whandle->plane >= VIRGL_MAX_PLANE_COUNT) {
+ return NULL;
+ }
+
if (whandle->offset != 0 && whandle->type == WINSYS_HANDLE_TYPE_SHARED) {
_debug_printf("attempt to import unsupported winsys offset %u\n",
whandle->offset);
@@ -346,8 +474,13 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws,
}
if (res) {
- struct virgl_hw_res *r = NULL;
- virgl_drm_resource_reference(&qdws->base, &r, res);
+ /* qdws->bo_{names,handles} hold weak pointers to virgl_hw_res. Because
+ * virgl_drm_resource_reference does not take qdws->bo_handles_mutex
+ * until it enters virgl_hw_res_destroy, there is a small window that
+ * the refcount can drop to zero. Call p_atomic_inc directly instead of
+ * virgl_drm_resource_reference to avoid hitting assert failures.
+ */
+ p_atomic_inc(&res->reference.count);
goto done;
}
@@ -380,21 +513,76 @@ virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws,
}
res->res_handle = info_arg.res_handle;
+ res->blob_mem = info_arg.blob_mem;
+ *blob_mem = info_arg.blob_mem;
res->size = info_arg.size;
+ res->maybe_untyped = info_arg.blob_mem ? true : false;
pipe_reference_init(&res->reference, 1);
p_atomic_set(&res->external, true);
res->num_cs_references = 0;
if (res->flink_name)
- util_hash_table_set(qdws->bo_names, (void *)(uintptr_t)res->flink_name, res);
- util_hash_table_set(qdws->bo_handles, (void *)(uintptr_t)res->bo_handle, res);
+ _mesa_hash_table_insert(qdws->bo_names, (void *)(uintptr_t)res->flink_name, res);
+ _mesa_hash_table_insert(qdws->bo_handles, (void *)(uintptr_t)res->bo_handle, res);
done:
mtx_unlock(&qdws->bo_handles_mutex);
return res;
}
+static void
+virgl_drm_winsys_resource_set_type(struct virgl_winsys *qws,
+ struct virgl_hw_res *res,
+ uint32_t format, uint32_t bind,
+ uint32_t width, uint32_t height,
+ uint32_t usage, uint64_t modifier,
+ uint32_t plane_count,
+ const uint32_t *plane_strides,
+ const uint32_t *plane_offsets)
+{
+ struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws);
+ uint32_t cmd[VIRGL_PIPE_RES_SET_TYPE_SIZE(VIRGL_MAX_PLANE_COUNT)];
+ struct drm_virtgpu_execbuffer eb;
+ int ret;
+
+ mtx_lock(&qdws->bo_handles_mutex);
+
+ if (!res->maybe_untyped) {
+ mtx_unlock(&qdws->bo_handles_mutex);
+ return;
+ }
+ res->maybe_untyped = false;
+
+ assert(plane_count && plane_count <= VIRGL_MAX_PLANE_COUNT);
+
+ cmd[0] = VIRGL_CMD0(VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE, 0, VIRGL_PIPE_RES_SET_TYPE_SIZE(plane_count));
+ cmd[VIRGL_PIPE_RES_SET_TYPE_RES_HANDLE] = res->res_handle,
+ cmd[VIRGL_PIPE_RES_SET_TYPE_FORMAT] = format;
+ cmd[VIRGL_PIPE_RES_SET_TYPE_BIND] = bind;
+ cmd[VIRGL_PIPE_RES_SET_TYPE_WIDTH] = width;
+ cmd[VIRGL_PIPE_RES_SET_TYPE_HEIGHT] = height;
+ cmd[VIRGL_PIPE_RES_SET_TYPE_USAGE] = usage;
+ cmd[VIRGL_PIPE_RES_SET_TYPE_MODIFIER_LO] = (uint32_t)modifier;
+ cmd[VIRGL_PIPE_RES_SET_TYPE_MODIFIER_HI] = (uint32_t)(modifier >> 32);
+ for (uint32_t i = 0; i < plane_count; i++) {
+ cmd[VIRGL_PIPE_RES_SET_TYPE_PLANE_STRIDE(i)] = plane_strides[i];
+ cmd[VIRGL_PIPE_RES_SET_TYPE_PLANE_OFFSET(i)] = plane_offsets[i];
+ }
+
+ memset(&eb, 0, sizeof(eb));
+ eb.command = (uintptr_t)cmd;
+ eb.size = (1 + VIRGL_PIPE_RES_SET_TYPE_SIZE(plane_count)) * 4;
+ eb.num_bo_handles = 1;
+ eb.bo_handles = (uintptr_t)&res->bo_handle;
+
+ ret = drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &eb);
+ if (ret == -1)
+ _debug_printf("failed to set resource type: %s", strerror(errno));
+
+ mtx_unlock(&qdws->bo_handles_mutex);
+}
+
static boolean virgl_drm_winsys_resource_get_handle(struct virgl_winsys *qws,
struct virgl_hw_res *res,
uint32_t stride,
@@ -417,7 +605,7 @@ static boolean virgl_drm_winsys_resource_get_handle(struct virgl_winsys *qws,
res->flink_name = flink.name;
mtx_lock(&qdws->bo_handles_mutex);
- util_hash_table_set(qdws->bo_names, (void *)(uintptr_t)res->flink_name, res);
+ _mesa_hash_table_insert(qdws->bo_names, (void *)(uintptr_t)res->flink_name, res);
mtx_unlock(&qdws->bo_handles_mutex);
}
whandle->handle = res->flink_name;
@@ -427,7 +615,7 @@ static boolean virgl_drm_winsys_resource_get_handle(struct virgl_winsys *qws,
if (drmPrimeHandleToFD(qdws->fd, res->bo_handle, DRM_CLOEXEC, (int*)&whandle->handle))
return FALSE;
mtx_lock(&qdws->bo_handles_mutex);
- util_hash_table_set(qdws->bo_handles, (void *)(uintptr_t)res->bo_handle, res);
+ _mesa_hash_table_insert(qdws->bo_handles, (void *)(uintptr_t)res->bo_handle, res);
mtx_unlock(&qdws->bo_handles_mutex);
}
@@ -662,7 +850,7 @@ virgl_drm_fence_create(struct virgl_winsys *vws, int fd, bool external)
assert(vws->supports_fences);
if (external) {
- fd = dup(fd);
+ fd = os_dupfd_cloexec(fd);
if (fd < 0)
return NULL;
}
@@ -772,7 +960,7 @@ static int virgl_drm_get_caps(struct virgl_winsys *vws,
virgl_ws_fill_new_caps_defaults(caps);
memset(&args, 0, sizeof(args));
- if (vdws->has_capset_query_fix) {
+ if (params[param_capset_fix].value) {
/* if we have the query fix - try and get cap set id 2 first */
args.cap_set_id = 2;
args.size = sizeof(union virgl_caps);
@@ -794,18 +982,6 @@ static int virgl_drm_get_caps(struct virgl_winsys *vws,
return ret;
}
-#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
-
-static unsigned handle_hash(void *key)
-{
- return PTR_TO_UINT(key);
-}
-
-static int handle_compare(void *key1, void *key2)
-{
- return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
-}
-
static struct pipe_fence_handle *
virgl_cs_create_fence(struct virgl_winsys *vws, int fd)
{
@@ -867,8 +1043,7 @@ static void virgl_fence_reference(struct virgl_winsys *vws,
if (vws->supports_fences) {
close(dfence->fd);
} else {
- struct virgl_drm_winsys *vdws = virgl_drm_winsys(vws);
- virgl_hw_res_destroy(vdws, dfence->hw_res);
+ virgl_drm_resource_reference(vws, &dfence->hw_res, NULL);
}
FREE(dfence);
}
@@ -901,7 +1076,7 @@ static int virgl_fence_get_fd(struct virgl_winsys *vws,
if (!vws->supports_fences)
return -1;
- return dup(fence->fd);
+ return os_dupfd_cloexec(fence->fd);
}
static int virgl_drm_get_version(int fd)
@@ -950,13 +1125,17 @@ virgl_drm_winsys_create(int drmFD)
struct virgl_drm_winsys *qdws;
int drm_version;
int ret;
- int gl = 0;
- struct drm_virtgpu_getparam getparam = {0};
- getparam.param = VIRTGPU_PARAM_3D_FEATURES;
- getparam.value = (uint64_t)(uintptr_t)&gl;
- ret = drmIoctl(drmFD, DRM_IOCTL_VIRTGPU_GETPARAM, &getparam);
- if (ret < 0 || !gl)
+ for (uint32_t i = 0; i < ARRAY_SIZE(params); i++) {
+ struct drm_virtgpu_getparam getparam = { 0 };
+ uint64_t value = 0;
+ getparam.param = params[i].param;
+ getparam.value = (uint64_t)(uintptr_t)&value;
+ ret = drmIoctl(drmFD, DRM_IOCTL_VIRTGPU_GETPARAM, &getparam);
+ params[i].value = (ret == 0) ? value : 0;
+ }
+
+ if (!params[param_3d_features].value)
return NULL;
drm_version = virgl_drm_get_version(drmFD);
@@ -974,8 +1153,10 @@ virgl_drm_winsys_create(int drmFD)
qdws);
(void) mtx_init(&qdws->mutex, mtx_plain);
(void) mtx_init(&qdws->bo_handles_mutex, mtx_plain);
- qdws->bo_handles = util_hash_table_create(handle_hash, handle_compare);
- qdws->bo_names = util_hash_table_create(handle_hash, handle_compare);
+ 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;
qdws->base.transfer_put = virgl_bo_transfer_put;
@@ -983,6 +1164,7 @@ virgl_drm_winsys_create(int drmFD)
qdws->base.resource_create = virgl_drm_winsys_resource_cache_create;
qdws->base.resource_reference = virgl_drm_resource_reference;
qdws->base.resource_create_from_handle = virgl_drm_winsys_resource_create_handle;
+ qdws->base.resource_set_type = virgl_drm_winsys_resource_set_type;
qdws->base.resource_get_handle = virgl_drm_winsys_resource_get_handle;
qdws->base.resource_map = virgl_drm_resource_map;
qdws->base.resource_wait = virgl_drm_resource_wait;
@@ -998,25 +1180,17 @@ virgl_drm_winsys_create(int drmFD)
qdws->base.fence_reference = virgl_fence_reference;
qdws->base.fence_server_sync = virgl_fence_server_sync;
qdws->base.fence_get_fd = virgl_fence_get_fd;
+ qdws->base.get_caps = virgl_drm_get_caps;
qdws->base.supports_fences = drm_version >= VIRGL_DRM_VERSION_FENCE_FD;
qdws->base.supports_encoded_transfers = 1;
- qdws->base.get_caps = virgl_drm_get_caps;
-
- uint32_t value = 0;
- getparam.param = VIRTGPU_PARAM_CAPSET_QUERY_FIX;
- getparam.value = (uint64_t)(uintptr_t)&value;
- ret = drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_GETPARAM, &getparam);
- if (ret == 0) {
- if (value == 1)
- qdws->has_capset_query_fix = true;
- }
-
+ qdws->base.supports_coherent = params[param_resource_blob].value &&
+ params[param_host_visible].value;
return &qdws->base;
}
-static struct util_hash_table *fd_tab = NULL;
+static struct hash_table *fd_tab = NULL;
static mtx_t virgl_screen_mutex = _MTX_INITIALIZER_NP;
static void
@@ -1029,7 +1203,7 @@ virgl_drm_screen_destroy(struct pipe_screen *pscreen)
destroy = --screen->refcnt == 0;
if (destroy) {
int fd = virgl_drm_winsys(screen->vws)->fd;
- util_hash_table_remove(fd_tab, intptr_to_pointer(fd));
+ _mesa_hash_table_remove_key(fd_tab, intptr_to_pointer(fd));
close(fd);
}
mtx_unlock(&virgl_screen_mutex);
@@ -1040,28 +1214,6 @@ virgl_drm_screen_destroy(struct pipe_screen *pscreen)
}
}
-static unsigned hash_fd(void *key)
-{
- int fd = pointer_to_intptr(key);
- struct stat stat;
- fstat(fd, &stat);
-
- return stat.st_dev ^ stat.st_ino ^ stat.st_rdev;
-}
-
-static int compare_fd(void *key1, void *key2)
-{
- int fd1 = pointer_to_intptr(key1);
- int fd2 = pointer_to_intptr(key2);
- struct stat stat1, stat2;
- fstat(fd1, &stat1);
- fstat(fd2, &stat2);
-
- return stat1.st_dev != stat2.st_dev ||
- stat1.st_ino != stat2.st_ino ||
- stat1.st_rdev != stat2.st_rdev;
-}
-
struct pipe_screen *
virgl_drm_screen_create(int fd, const struct pipe_screen_config *config)
{
@@ -1069,7 +1221,7 @@ virgl_drm_screen_create(int fd, const struct pipe_screen_config *config)
mtx_lock(&virgl_screen_mutex);
if (!fd_tab) {
- fd_tab = util_hash_table_create(hash_fd, compare_fd);
+ fd_tab = util_hash_table_create_fd_keys();
if (!fd_tab)
goto unlock;
}
@@ -1079,7 +1231,7 @@ virgl_drm_screen_create(int fd, const struct pipe_screen_config *config)
virgl_screen(pscreen)->refcnt++;
} else {
struct virgl_winsys *vws;
- int dup_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+ int dup_fd = os_dupfd_cloexec(fd);
vws = virgl_drm_winsys_create(dup_fd);
if (!vws) {
@@ -1089,7 +1241,7 @@ virgl_drm_screen_create(int fd, const struct pipe_screen_config *config)
pscreen = virgl_create_screen(vws, config);
if (pscreen) {
- util_hash_table_set(fd_tab, intptr_to_pointer(dup_fd), pscreen);
+ _mesa_hash_table_insert(fd_tab, intptr_to_pointer(dup_fd), pscreen);
/* Bit of a hack, to avoid circular linkage dependency,
* ie. pipe driver having to call in to winsys, we
diff --git a/lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h b/lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h
index 3a2c476a0..28fb9715a 100644
--- a/lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h
+++ b/lib/mesa/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h
@@ -32,10 +32,11 @@
#include "virgl_resource_cache.h"
struct pipe_fence_handle;
-struct util_hash_table;
+struct hash_table;
struct virgl_hw_res {
struct pipe_reference reference;
+ enum pipe_texture_target target;
uint32_t res_handle;
uint32_t bo_handle;
int num_cs_references;
@@ -44,13 +45,42 @@ struct virgl_hw_res {
struct virgl_resource_cache_entry cache_entry;
uint32_t bind;
+ uint32_t flags;
uint32_t flink_name;
+ /* false when the resource is known to be typed */
+ bool maybe_untyped;
+
/* true when the resource is imported or exported */
int external;
/* false when the resource is known to be idle */
int maybe_busy;
+ uint32_t blob_mem;
+};
+
+
+struct param {
+ uint64_t param;
+ const char *name;
+ uint64_t value;
+};
+
+enum param_id {
+ param_3d_features,
+ param_capset_fix,
+ param_resource_blob,
+ param_host_visible,
+ param_max,
+};
+
+#define PARAM(x) (struct param) { x, #x, 0 }
+
+struct param params[] = { PARAM(VIRTGPU_PARAM_3D_FEATURES),
+ PARAM(VIRTGPU_PARAM_CAPSET_QUERY_FIX),
+ PARAM(VIRTGPU_PARAM_RESOURCE_BLOB),
+ PARAM(VIRTGPU_PARAM_HOST_VISIBLE),
+ PARAM(VIRTGPU_PARAM_CROSS_DEVICE)
};
struct virgl_drm_winsys
@@ -60,10 +90,10 @@ struct virgl_drm_winsys
struct virgl_resource_cache cache;
mtx_t mutex;
- struct util_hash_table *bo_handles;
- struct util_hash_table *bo_names;
+ int32_t blob_id;
+ struct hash_table *bo_handles;
+ struct hash_table *bo_names;
mtx_t bo_handles_mutex;
- bool has_capset_query_fix;
};
struct virgl_drm_fence {
diff --git a/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c b/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c
index 1bb5d387c..669cd763e 100644
--- a/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c
+++ b/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c
@@ -26,7 +26,7 @@
#include "util/format/u_format.h"
#include "util/u_inlines.h"
#include "util/os_time.h"
-#include "state_tracker/sw_winsys.h"
+#include "frontend/sw_winsys.h"
#include "os/os_mman.h"
#include "virgl_vtest_winsys.h"
@@ -181,7 +181,7 @@ static void virgl_hw_res_destroy(struct virgl_vtest_winsys *vtws,
if (res->ptr)
os_munmap(res->ptr, res->size);
} else {
- free(res->ptr);
+ align_free(res->ptr);
}
FREE(res);
@@ -291,7 +291,7 @@ virgl_vtest_winsys_resource_create(struct virgl_winsys *vws,
}
out:
- virgl_resource_cache_entry_init(&res->cache_entry, size, bind, format);
+ virgl_resource_cache_entry_init(&res->cache_entry, size, bind, format, 0);
res->res_handle = handle++;
pipe_reference_init(&res->reference, 1);
p_atomic_set(&res->num_cs_references, 0);
@@ -347,6 +347,7 @@ virgl_vtest_winsys_resource_cache_create(struct virgl_winsys *vws,
uint32_t array_size,
uint32_t last_level,
uint32_t nr_samples,
+ uint32_t flags,
uint32_t size)
{
struct virgl_vtest_winsys *vtws = virgl_vtest_winsys(vws);
@@ -359,7 +360,7 @@ virgl_vtest_winsys_resource_cache_create(struct virgl_winsys *vws,
mtx_lock(&vtws->mutex);
entry = virgl_resource_cache_remove_compatible(&vtws->cache, size,
- bind, format);
+ bind, format, 0);
if (entry) {
res = cache_entry_container_res(entry);
mtx_unlock(&vtws->mutex);
diff --git a/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.h b/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.h
index 27b417281..4254a551f 100644
--- a/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.h
+++ b/lib/mesa/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.h
@@ -31,7 +31,7 @@
#include "os/os_thread.h"
#include "virgl/virgl_winsys.h"
-#include "vtest_protocol.h"
+#include "vtest/vtest_protocol.h"
#include "virgl_resource_cache.h"
struct pipe_fence_handle;
diff --git a/lib/mesa/src/gallium/winsys/virgl/vtest/vtest_protocol.h b/lib/mesa/src/gallium/winsys/virgl/vtest/vtest_protocol.h
deleted file mode 100644
index 86d197f00..000000000
--- a/lib/mesa/src/gallium/winsys/virgl/vtest/vtest_protocol.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2014, 2015 Red Hat.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef VTEST_PROTOCOL
-#define VTEST_PROTOCOL
-
-#define VTEST_DEFAULT_SOCKET_NAME "/tmp/.virgl_test"
-
-/* 32-bit length field */
-/* 32-bit cmd field */
-#define VTEST_HDR_SIZE 2
-#define VTEST_CMD_LEN 0 /* length of data */
-#define VTEST_CMD_ID 1
-#define VTEST_CMD_DATA_START 2
-
-/* vtest cmds */
-#define VCMD_GET_CAPS 1
-
-#define VCMD_RESOURCE_CREATE 2
-#define VCMD_RESOURCE_UNREF 3
-
-#define VCMD_TRANSFER_GET 4
-#define VCMD_TRANSFER_PUT 5
-
-#define VCMD_SUBMIT_CMD 6
-
-#define VCMD_RESOURCE_BUSY_WAIT 7
-
-/* pass the process cmd line for debugging */
-#define VCMD_CREATE_RENDERER 8
-/* get caps */
-/* 0 length cmd */
-/* resp VCMD_GET_CAPS + caps */
-
-#define VCMD_RES_CREATE_SIZE 10
-#define VCMD_RES_CREATE_RES_HANDLE 0
-#define VCMD_RES_CREATE_TARGET 1
-#define VCMD_RES_CREATE_FORMAT 2
-#define VCMD_RES_CREATE_BIND 3
-#define VCMD_RES_CREATE_WIDTH 4
-#define VCMD_RES_CREATE_HEIGHT 5
-#define VCMD_RES_CREATE_DEPTH 6
-#define VCMD_RES_CREATE_ARRAY_SIZE 7
-#define VCMD_RES_CREATE_LAST_LEVEL 8
-#define VCMD_RES_CREATE_NR_SAMPLES 9
-
-#define VCMD_RES_UNREF_SIZE 1
-#define VCMD_RES_UNREF_RES_HANDLE 0
-
-#define VCMD_TRANSFER_HDR_SIZE 11
-#define VCMD_TRANSFER_RES_HANDLE 0
-#define VCMD_TRANSFER_LEVEL 1
-#define VCMD_TRANSFER_STRIDE 2
-#define VCMD_TRANSFER_LAYER_STRIDE 3
-#define VCMD_TRANSFER_X 4
-#define VCMD_TRANSFER_Y 5
-#define VCMD_TRANSFER_Z 6
-#define VCMD_TRANSFER_WIDTH 7
-#define VCMD_TRANSFER_HEIGHT 8
-#define VCMD_TRANSFER_DEPTH 9
-#define VCMD_TRANSFER_DATA_SIZE 10
-
-#define VCMD_BUSY_WAIT_FLAG_WAIT 1
-
-#define VCMD_BUSY_WAIT_SIZE 2
-#define VCMD_BUSY_WAIT_HANDLE 0
-#define VCMD_BUSY_WAIT_FLAGS 1
-
-#endif