From 5dce0053e5ff0431a3ef5b3b38e18fa4baaf5836 Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Tue, 24 Mar 2020 10:56:41 -0700 Subject: [PATCH] vrend_renderer: add map/unmap/map_info For non-exportable memory, add map/unmap. For additional validation, query virglrenderer about the preferred caching type. The response will be returned in to the guest in virtio_gpu_resp_map_info. Acked-by: Chia-I Wu Reviewed-by: Gert Wollny --- src/virglrenderer.c | 27 ++++++++++++++++++++++++++ src/virglrenderer.h | 13 +++++++++++++ src/vrend_renderer.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ src/vrend_renderer.h | 10 ++++++++++ 4 files changed, 95 insertions(+) diff --git a/src/virglrenderer.c b/src/virglrenderer.c index 5f9ad56..62a3e45 100644 --- a/src/virglrenderer.c +++ b/src/virglrenderer.c @@ -676,3 +676,30 @@ int virgl_renderer_resource_create_blob(const struct virgl_renderer_resource_cre return 0; } + +int virgl_renderer_resource_map(uint32_t res_handle, void **map, uint64_t *out_size) +{ + struct virgl_resource *res = virgl_resource_lookup(res_handle); + if (!res || !res->pipe_resource) + return -EINVAL; + + return vrend_renderer_resource_map(res->pipe_resource, map, out_size); +} + +int virgl_renderer_resource_unmap(uint32_t res_handle) +{ + struct virgl_resource *res = virgl_resource_lookup(res_handle); + if (!res || !res->pipe_resource) + return -EINVAL; + + return vrend_renderer_resource_unmap(res->pipe_resource); +} + +int virgl_renderer_resource_get_map_info(uint32_t res_handle, uint32_t *map_info) +{ + struct virgl_resource *res = virgl_resource_lookup(res_handle); + if (!res || !res->pipe_resource) + return -EINVAL; + + return vrend_renderer_resource_get_map_info(res->pipe_resource, map_info); +} diff --git a/src/virglrenderer.h b/src/virglrenderer.h index f91804d..f9443b2 100644 --- a/src/virglrenderer.h +++ b/src/virglrenderer.h @@ -258,4 +258,17 @@ struct virgl_renderer_resource_create_blob_args VIRGL_EXPORT int virgl_renderer_resource_create_blob(const struct virgl_renderer_resource_create_blob_args *args); + +VIRGL_EXPORT int virgl_renderer_resource_map(uint32_t res_handle, void **map, uint64_t *out_size); + +VIRGL_EXPORT int virgl_renderer_resource_unmap(uint32_t res_handle); + +#define VIRGL_RENDERER_MAP_CACHE_MASK 0x0f +#define VIRGL_RENDERER_MAP_CACHE_NONE 0x00 +#define VIRGL_RENDERER_MAP_CACHE_CACHED 0x01 +#define VIRGL_RENDERER_MAP_CACHE_UNCACHED 0x02 +#define VIRGL_RENDERER_MAP_CACHE_WC 0x03 + +VIRGL_EXPORT int virgl_renderer_resource_get_map_info(uint32_t res_handle, uint32_t *map_info); + #endif diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index cb5bd85..e5b8630 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -310,6 +310,8 @@ struct global_renderer_state { float tess_factors[6]; bool bgra_srgb_emulation_loaded; + /* inferred GL caching type */ + uint32_t inferred_gl_caching_type; }; static struct global_renderer_state vrend_state; @@ -6437,6 +6439,11 @@ static void vrend_resource_gbm_init(struct vrend_resource *gr, uint32_t format) gr->gbm_bo = bo; gr->storage_bits |= VREND_STORAGE_GBM_BUFFER; + /* This is true so far, but maybe gbm_bo_get_caching_type is needed in the future. */ + if (!strcmp(gbm_device_get_backend_name(gbm->device), "i915")) + gr->map_info = VIRGL_MAP_CACHE_CACHED; + else + gr->map_info = VIRGL_MAP_CACHE_WC; if (!virgl_gbm_gpu_import_required(gr->base.bind)) return; @@ -10367,3 +10374,41 @@ struct pipe_resource *vrend_get_blob_pipe(struct vrend_context *ctx, uint64_t bl return NULL; } + +int vrend_renderer_resource_get_map_info(struct pipe_resource *pres, uint32_t *map_info) +{ + struct vrend_resource *res = (struct vrend_resource *)pres; + if (!res->map_info) + return -EINVAL; + + *map_info = res->map_info; + return 0; +} + +int vrend_renderer_resource_map(struct pipe_resource *pres, void **map, uint64_t *out_size) +{ + struct vrend_resource *res = (struct vrend_resource *)pres; + if (!has_bits(res->storage_bits, VREND_STORAGE_GL_BUFFER | VREND_STORAGE_GL_IMMUTABLE)) + return -EINVAL; + + glBindBufferARB(res->target, res->id); + *map = glMapBufferRange(res->target, 0, res->size, res->buffer_storage_flags); + if (!*map) + return -EINVAL; + + glBindBufferARB(res->target, 0); + *out_size = res->size; + return 0; +} + +int vrend_renderer_resource_unmap(struct pipe_resource *pres) +{ + struct vrend_resource *res = (struct vrend_resource *)pres; + if (!has_bits(res->storage_bits, VREND_STORAGE_GL_BUFFER | VREND_STORAGE_GL_IMMUTABLE)) + return -EINVAL; + + glBindBufferARB(res->target, res->id); + glUnmapBuffer(res->target); + glBindBufferARB(res->target, 0); + return 0; +} diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index b14fae9..66c1ac4 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -77,6 +77,7 @@ extern struct virgl_gbm *gbm; struct vrend_resource { struct pipe_resource base; uint32_t storage_bits; + uint32_t map_info; GLuint id; GLenum target; @@ -99,6 +100,9 @@ struct vrend_resource { uint64_t mipmap_offsets[VR_MAX_TEXTURE_2D_LEVELS]; void *gbm_bo, *egl_image; void *aux_plane_egl_image[VIRGL_GBM_MAX_PLANES]; + + uint64_t size; + GLbitfield buffer_storage_flags; uint32_t blob_id; struct list_head head; @@ -497,4 +501,10 @@ vrend_renderer_pipe_resource_create(struct vrend_context *ctx, uint32_t blob_id, struct pipe_resource *vrend_get_blob_pipe(struct vrend_context *ctx, uint64_t blob_id); +int vrend_renderer_resource_get_map_info(struct pipe_resource *pres, uint32_t *map_info); + +int vrend_renderer_resource_map(struct pipe_resource *pres, void **map, uint64_t *out_size); + +int vrend_renderer_resource_unmap(struct pipe_resource *pres); + #endif