diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c index f8edcc182bc..48205174490 100644 --- a/src/gallium/drivers/virgl/virgl_resource.c +++ b/src/gallium/drivers/virgl/virgl_resource.c @@ -708,6 +708,8 @@ static struct pipe_resource *virgl_resource_from_handle(struct pipe_screen *scre { uint32_t winsys_stride, plane_offset, plane; uint64_t modifier; + uint32_t storage_size; + struct virgl_screen *vs = virgl_screen(screen); if (templ->target == PIPE_BUFFER) return NULL; @@ -739,6 +741,19 @@ static struct pipe_resource *virgl_resource_from_handle(struct pipe_screen *scre return NULL; } + /* + * If the overall resource is larger than a single page in size, we can + * compare it with the amount of memory allocated on the guest to determine + * if we should be using the staging path. + * + * If not, the decision is not as clear. However, since the resource can + * fit within a single page, the import will function correctly. + */ + storage_size = vs->vws->resource_get_storage_size(vs->vws, res->hw_res); + + if (res->metadata.total_size > storage_size) + res->use_staging = 1; + /* assign blob resource a type in case it was created untyped */ if (res->blob_mem && plane == 0 && (vs->caps.caps.v2.capability_bits_v2 & VIRGL_CAP_V2_UNTYPED_RESOURCE)) { diff --git a/src/gallium/drivers/virgl/virgl_winsys.h b/src/gallium/drivers/virgl/virgl_winsys.h index 45c3819ed8e..13e82b033b4 100644 --- a/src/gallium/drivers/virgl/virgl_winsys.h +++ b/src/gallium/drivers/virgl/virgl_winsys.h @@ -103,6 +103,9 @@ struct virgl_winsys { uint32_t stride, struct winsys_handle *whandle); + uint32_t (*resource_get_storage_size)(struct virgl_winsys* vws, + struct virgl_hw_res* res); + struct virgl_cmd_buf *(*cmd_buf_create)(struct virgl_winsys *ws, uint32_t size); void (*cmd_buf_destroy)(struct virgl_cmd_buf *buf); diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c index 20dc3450f91..9c1137ada49 100644 --- a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c +++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c @@ -459,6 +459,13 @@ alloc: return res; } +static uint32_t +virgl_drm_winsys_resource_get_storage_size(struct virgl_winsys *qws, + struct virgl_hw_res *res) +{ + return res->size; +} + static struct virgl_hw_res * virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws, struct winsys_handle *whandle, @@ -1250,6 +1257,7 @@ virgl_drm_winsys_create(int drmFD) 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_get_storage_size = virgl_drm_winsys_resource_get_storage_size; qdws->base.resource_map = virgl_drm_resource_map; qdws->base.resource_wait = virgl_drm_resource_wait; qdws->base.resource_is_busy = virgl_drm_resource_is_busy;