| /* |
| * Copyright 2020 Google LLC |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| #ifndef VKR_CONTEXT_H |
| #define VKR_CONTEXT_H |
| |
| #include "vkr_common.h" |
| |
| #include "venus-protocol/vn_protocol_renderer_defines.h" |
| #include "virgl_context.h" |
| #include "vrend_iov.h" |
| |
| #include "vkr_cs.h" |
| |
| struct virgl_resource; |
| |
| /* |
| * When a virgl_resource is attached in vkr_context_attach_resource, a |
| * vkr_resource_attachment is created. A vkr_resource_attachment is valid |
| * until the resource it tracks is detached. |
| */ |
| struct vkr_resource_attachment { |
| struct virgl_resource *resource; |
| |
| /* if VIRGL_RESOURCE_FD_SHM, this is the mapping of the shm and iov below |
| * points to this |
| */ |
| struct iovec shm_iov; |
| |
| const struct iovec *iov; |
| int iov_count; |
| }; |
| |
| enum vkr_context_validate_level { |
| /* no validation */ |
| VKR_CONTEXT_VALIDATE_NONE, |
| /* force enabling a subset of the validation layer */ |
| VKR_CONTEXT_VALIDATE_ON, |
| /* force enabling the validation layer */ |
| VKR_CONTEXT_VALIDATE_FULL, |
| }; |
| |
| struct vkr_cpu_sync { |
| uint32_t flags; |
| uint32_t ring_idx; |
| uint64_t fence_id; |
| |
| struct list_head head; |
| }; |
| |
| struct vkr_context { |
| struct virgl_context base; |
| |
| char *debug_name; |
| enum vkr_context_validate_level validate_level; |
| bool validate_fatal; |
| |
| mtx_t mutex; |
| |
| struct list_head rings; |
| struct hash_table *object_table; |
| struct hash_table *resource_table; |
| |
| struct vkr_cs_encoder encoder; |
| struct vkr_cs_decoder decoder; |
| struct vn_dispatch_context dispatch; |
| |
| int fence_eventfd; |
| struct list_head busy_queues; |
| struct list_head signaled_syncs; |
| struct list_head signaled_cpu_syncs; |
| |
| struct vkr_queue *sync_queues[64]; |
| |
| struct vkr_instance *instance; |
| char *instance_name; |
| }; |
| |
| void |
| vkr_context_free_resource(struct hash_entry *entry); |
| |
| static inline void |
| vkr_context_add_resource(struct vkr_context *ctx, struct vkr_resource_attachment *att) |
| { |
| assert(!_mesa_hash_table_search(ctx->resource_table, &att->resource->res_id)); |
| _mesa_hash_table_insert(ctx->resource_table, &att->resource->res_id, att); |
| } |
| |
| static inline void |
| vkr_context_remove_resource(struct vkr_context *ctx, uint32_t res_id) |
| { |
| struct hash_entry *entry = _mesa_hash_table_search(ctx->resource_table, &res_id); |
| if (likely(entry)) { |
| vkr_context_free_resource(entry); |
| _mesa_hash_table_remove(ctx->resource_table, entry); |
| } |
| } |
| |
| static inline struct vkr_resource_attachment * |
| vkr_context_get_resource(struct vkr_context *ctx, uint32_t res_id) |
| { |
| const struct hash_entry *entry = _mesa_hash_table_search(ctx->resource_table, &res_id); |
| return likely(entry) ? entry->data : NULL; |
| } |
| |
| static inline bool |
| vkr_context_validate_object_id(struct vkr_context *ctx, vkr_object_id id) |
| { |
| if (unlikely(!id || _mesa_hash_table_search(ctx->object_table, &id))) { |
| vkr_log("invalid object id %" PRIu64, id); |
| vkr_cs_decoder_set_fatal(&ctx->decoder); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| static inline void * |
| vkr_context_alloc_object(UNUSED struct vkr_context *ctx, |
| size_t size, |
| VkObjectType type, |
| const void *id_handle) |
| { |
| const vkr_object_id id = vkr_cs_handle_load_id((const void **)id_handle, type); |
| if (!vkr_context_validate_object_id(ctx, id)) |
| return NULL; |
| |
| return vkr_object_alloc(size, type, id); |
| } |
| |
| void |
| vkr_context_free_object(struct hash_entry *entry); |
| |
| static inline void |
| vkr_context_add_object(struct vkr_context *ctx, struct vkr_object *obj) |
| { |
| assert(vkr_is_recognized_object_type(obj->type)); |
| assert(obj->id); |
| assert(!_mesa_hash_table_search(ctx->object_table, &obj->id)); |
| |
| _mesa_hash_table_insert(ctx->object_table, &obj->id, obj); |
| } |
| |
| static inline void |
| vkr_context_remove_object(struct vkr_context *ctx, struct vkr_object *obj) |
| { |
| assert(_mesa_hash_table_search(ctx->object_table, &obj->id)); |
| |
| struct hash_entry *entry = _mesa_hash_table_search(ctx->object_table, &obj->id); |
| if (likely(entry)) { |
| vkr_context_free_object(entry); |
| _mesa_hash_table_remove(ctx->object_table, entry); |
| } |
| } |
| |
| static inline void |
| vkr_context_remove_objects(struct vkr_context *ctx, struct list_head *objects) |
| { |
| struct vkr_object *obj, *tmp; |
| LIST_FOR_EACH_ENTRY_SAFE (obj, tmp, objects, track_head) |
| vkr_context_remove_object(ctx, obj); |
| /* objects should be reinitialized if to be reused */ |
| } |
| |
| static inline void * |
| vkr_context_get_object(struct vkr_context *ctx, vkr_object_id obj_id) |
| { |
| const struct hash_entry *entry = _mesa_hash_table_search(ctx->object_table, &obj_id); |
| return likely(entry) ? entry->data : NULL; |
| } |
| |
| static inline const char * |
| vkr_context_get_name(const struct vkr_context *ctx) |
| { |
| /* ctx->instance_name is the application name while ctx->debug_name is |
| * usually the guest process name or the hypervisor name. This never |
| * returns NULL because ctx->debug_name is never NULL. |
| */ |
| return ctx->instance_name ? ctx->instance_name : ctx->debug_name; |
| } |
| |
| void |
| vkr_context_add_instance(struct vkr_context *ctx, |
| struct vkr_instance *instance, |
| const char *name); |
| |
| void |
| vkr_context_remove_instance(struct vkr_context *ctx, struct vkr_instance *instance); |
| |
| #endif /* VKR_CONTEXT_H */ |