blob: fa9cd9d73c0e829f35f5d940ab819d52a643d845 [file] [log] [blame]
/*
* Copyright 2020 Google LLC
* SPDX-License-Identifier: MIT
*/
#include "vkr_common.h"
#include "venus-protocol/vn_protocol_renderer_info.h"
#include "virglrenderer_hw.h"
#include "vkr_context.h"
struct vkr_renderer_state {
const struct vkr_renderer_callbacks *cbs;
/* track the vkr_context */
struct list_head contexts;
};
struct vkr_renderer_state vkr_state;
size_t
vkr_get_capset(void *capset)
{
struct virgl_renderer_capset_venus *c = capset;
if (c) {
memset(c, 0, sizeof(*c));
c->wire_format_version = vn_info_wire_format_version();
c->vk_xml_version = vn_info_vk_xml_version();
c->vk_ext_command_serialization_spec_version =
vkr_extension_get_spec_version("VK_EXT_command_serialization");
c->vk_mesa_venus_protocol_spec_version =
vkr_extension_get_spec_version("VK_MESA_venus_protocol");
/* After https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/688,
* this flag is used to indicate render server config.
*/
c->supports_blob_id_0 = true;
uint32_t ext_mask[VN_INFO_EXTENSION_MAX_NUMBER / 32 + 1] = { 0 };
vn_info_extension_mask_init(ext_mask);
static_assert(sizeof(ext_mask) <= sizeof(c->vk_extension_mask1),
"Time to extend venus capset with vk_extension_mask2");
memcpy(c->vk_extension_mask1, ext_mask, sizeof(ext_mask));
/* set bit 0 to enable the extension mask(s) */
assert(!(c->vk_extension_mask1[0] & 0x1u));
c->vk_extension_mask1[0] |= 0x1u;
c->allow_vk_wait_syncs = 1;
c->supports_multiple_timelines = 1;
}
return sizeof(*c);
}
bool
vkr_renderer_init(uint32_t flags, const struct vkr_renderer_callbacks *cbs)
{
TRACE_INIT();
TRACE_FUNC();
static const uint32_t required_flags =
VKR_RENDERER_THREAD_SYNC | VKR_RENDERER_ASYNC_FENCE_CB;
if ((flags & required_flags) != required_flags)
return false;
vkr_debug_init();
virgl_log_set_logger(cbs->debug_logger);
vkr_state.cbs = cbs;
list_inithead(&vkr_state.contexts);
return true;
}
void
vkr_renderer_fini(void)
{
struct vkr_context *ctx, *tmp;
LIST_FOR_EACH_ENTRY_SAFE (ctx, tmp, &vkr_state.contexts, head)
vkr_context_destroy(ctx);
list_inithead(&vkr_state.contexts);
vkr_state.cbs = NULL;
}
static struct vkr_context *
vkr_renderer_lookup_context(uint32_t ctx_id)
{
list_for_each_entry (struct vkr_context, ctx, &vkr_state.contexts, head) {
if (ctx->ctx_id == ctx_id)
return ctx;
}
return NULL;
}
bool
vkr_renderer_create_context(uint32_t ctx_id,
uint32_t ctx_flags,
uint32_t nlen,
const char *name)
{
TRACE_FUNC();
assert(ctx_id);
assert(!(ctx_flags & ~VIRGL_RENDERER_CONTEXT_FLAG_CAPSET_ID_MASK));
if ((ctx_flags & VIRGL_RENDERER_CONTEXT_FLAG_CAPSET_ID_MASK) !=
VIRGL_RENDERER_CAPSET_VENUS)
return false;
/* duplicate ctx creation between server and vkr is invalid */
struct vkr_context *ctx = vkr_renderer_lookup_context(ctx_id);
if (ctx)
return false;
ctx = vkr_context_create(ctx_id, vkr_state.cbs->retire_fence, nlen, name);
if (!ctx)
return false;
list_addtail(&ctx->head, &vkr_state.contexts);
return true;
}
void
vkr_renderer_destroy_context(uint32_t ctx_id)
{
TRACE_FUNC();
struct vkr_context *ctx = vkr_renderer_lookup_context(ctx_id);
if (!ctx)
return;
list_del(&ctx->head);
vkr_context_destroy(ctx);
}
bool
vkr_renderer_submit_cmd(uint32_t ctx_id, void *cmd, uint32_t size)
{
TRACE_FUNC();
struct vkr_context *ctx = vkr_renderer_lookup_context(ctx_id);
if (!ctx)
return false;
return vkr_context_submit_cmd(ctx, cmd, size);
}
bool
vkr_renderer_submit_fence(uint32_t ctx_id,
uint32_t flags,
uint64_t ring_idx,
uint64_t fence_id)
{
TRACE_FUNC();
struct vkr_context *ctx = vkr_renderer_lookup_context(ctx_id);
if (!ctx)
return false;
assert(vkr_state.cbs->retire_fence);
return vkr_context_submit_fence(ctx, flags, ring_idx, fence_id);
}
bool
vkr_renderer_create_resource(uint32_t ctx_id,
uint32_t res_id,
uint64_t blob_id,
uint64_t blob_size,
uint32_t blob_flags,
enum virgl_resource_fd_type *out_fd_type,
int *out_res_fd,
uint32_t *out_map_info,
struct virgl_resource_vulkan_info *out_vulkan_info)
{
TRACE_FUNC();
assert(res_id);
assert(blob_size);
struct vkr_context *ctx = vkr_renderer_lookup_context(ctx_id);
if (!ctx)
return false;
struct virgl_context_blob blob;
if (!vkr_context_create_resource(ctx, res_id, blob_id, blob_size, blob_flags, &blob))
return false;
assert(blob.type == VIRGL_RESOURCE_FD_SHM || blob.type == VIRGL_RESOURCE_FD_DMABUF ||
blob.type == VIRGL_RESOURCE_FD_OPAQUE);
*out_fd_type = blob.type;
*out_res_fd = blob.u.fd;
*out_map_info = blob.map_info;
if (blob.type == VIRGL_RESOURCE_FD_OPAQUE) {
assert(out_vulkan_info);
*out_vulkan_info = blob.vulkan_info;
}
return true;
}
bool
vkr_renderer_import_resource(uint32_t ctx_id,
uint32_t res_id,
enum virgl_resource_fd_type fd_type,
int fd,
uint64_t size)
{
TRACE_FUNC();
assert(res_id);
assert(fd_type == VIRGL_RESOURCE_FD_DMABUF || fd_type == VIRGL_RESOURCE_FD_OPAQUE);
assert(fd >= 0);
assert(size);
struct vkr_context *ctx = vkr_renderer_lookup_context(ctx_id);
if (!ctx)
return false;
return vkr_context_import_resource(ctx, res_id, fd_type, fd, size);
}
void
vkr_renderer_destroy_resource(uint32_t ctx_id, uint32_t res_id)
{
TRACE_FUNC();
struct vkr_context *ctx = vkr_renderer_lookup_context(ctx_id);
if (ctx)
vkr_context_destroy_resource(ctx, res_id);
}