vrend: add support for VIRGL_CAP_V2_UNTYPED_RESOURCE

An untyped resource is a virgl_resource without pipe_resource while
vrend_context works with pipe_resources exclusively.  When an untyped
resource is attached, we defer the insersion into res_hash until
VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE is submitted.

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Acked-by: Gert Wollny <gert.wollny@collabora.com>
Acked-by: Gurchetan Singh <gurchetansingh@chromium.org> (protocol)
macos/master
Chia-I Wu 4 years ago
parent 115a07a171
commit f5a45fe97e
  1. 1
      src/virgl_hw.h
  2. 14
      src/virgl_protocol.h
  3. 1
      src/vrend_debug.c
  4. 31
      src/vrend_decode.c
  5. 127
      src/vrend_renderer.c
  6. 18
      src/vrend_renderer.h

@ -407,6 +407,7 @@ enum virgl_formats {
/* These are used by the capability_bits_v2 field in virgl_caps_v2. */ /* These are used by the capability_bits_v2 field in virgl_caps_v2. */
#define VIRGL_CAP_V2_BLEND_EQUATION (1 << 0) #define VIRGL_CAP_V2_BLEND_EQUATION (1 << 0)
#define VIRGL_CAP_V2_UNTYPED_RESOURCE (1 << 1)
/* virgl bind flags - these are compatible with mesa 10.5 gallium. /* virgl bind flags - these are compatible with mesa 10.5 gallium.
* but are fixed, no other should be passed to virgl either. * but are fixed, no other should be passed to virgl either.

@ -102,6 +102,7 @@ enum virgl_context_cmd {
VIRGL_CCMD_SET_TWEAKS, VIRGL_CCMD_SET_TWEAKS,
VIRGL_CCMD_CLEAR_TEXTURE, VIRGL_CCMD_CLEAR_TEXTURE,
VIRGL_CCMD_PIPE_RESOURCE_CREATE, VIRGL_CCMD_PIPE_RESOURCE_CREATE,
VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE,
VIRGL_MAX_COMMANDS VIRGL_MAX_COMMANDS
}; };
@ -636,4 +637,17 @@ enum vrend_tweak_type {
#define VIRGL_PIPE_RES_CREATE_FLAGS 10 #define VIRGL_PIPE_RES_CREATE_FLAGS 10
#define VIRGL_PIPE_RES_CREATE_BLOB_ID 11 #define VIRGL_PIPE_RES_CREATE_BLOB_ID 11
/* VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE */
#define VIRGL_PIPE_RES_SET_TYPE_SIZE(nplanes) (8 + (nplanes) * 2)
#define VIRGL_PIPE_RES_SET_TYPE_RES_HANDLE 1
#define VIRGL_PIPE_RES_SET_TYPE_FORMAT 2
#define VIRGL_PIPE_RES_SET_TYPE_BIND 3
#define VIRGL_PIPE_RES_SET_TYPE_WIDTH 4
#define VIRGL_PIPE_RES_SET_TYPE_HEIGHT 5
#define VIRGL_PIPE_RES_SET_TYPE_USAGE 6
#define VIRGL_PIPE_RES_SET_TYPE_MODIFIER_LO 7
#define VIRGL_PIPE_RES_SET_TYPE_MODIFIER_HI 8
#define VIRGL_PIPE_RES_SET_TYPE_PLANE_STRIDE(plane) (9 + (plane) * 2)
#define VIRGL_PIPE_RES_SET_TYPE_PLANE_OFFSET(plane) (10 + (plane) * 2)
#endif #endif

@ -78,6 +78,7 @@ static const char *command_names[VIRGL_MAX_COMMANDS] = {
"TWEAK", "TWEAK",
"CLEAR_TEXTURE" "CLEAR_TEXTURE"
"PIPE_RESOURCE_CREATE", "PIPE_RESOURCE_CREATE",
"PIPE_RESOURCE_SET_TYPE",
}; };
static const char *object_type_names[VIRGL_MAX_OBJECTS] = { static const char *object_type_names[VIRGL_MAX_OBJECTS] = {

@ -1431,6 +1431,34 @@ static int vrend_decode_pipe_resource_create(struct vrend_context *ctx, const ui
return vrend_renderer_pipe_resource_create(ctx, blob_id, &args); return vrend_renderer_pipe_resource_create(ctx, blob_id, &args);
} }
static int vrend_decode_pipe_resource_set_type(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
{
struct vrend_renderer_resource_set_type_args args = { 0 };
uint32_t res_id;
if (length >= VIRGL_PIPE_RES_SET_TYPE_SIZE(0))
args.plane_count = (length - VIRGL_PIPE_RES_SET_TYPE_SIZE(0)) / 2;
if (length != VIRGL_PIPE_RES_SET_TYPE_SIZE(args.plane_count) ||
!args.plane_count || args.plane_count > VIRGL_GBM_MAX_PLANES)
return EINVAL;
res_id = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_RES_HANDLE);
args.format = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_FORMAT);
args.bind = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_BIND);
args.width = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_WIDTH);
args.height = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_HEIGHT);
args.usage = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_USAGE);
args.modifier = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_MODIFIER_LO);
args.modifier |= (uint64_t)get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_MODIFIER_HI) << 32;
for (uint32_t i = 0; i < args.plane_count; i++) {
args.plane_strides[i] = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_PLANE_STRIDE(i));
args.plane_offsets[i] = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_PLANE_OFFSET(i));
}
return vrend_renderer_pipe_resource_set_type(ctx, res_id, &args);
}
static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx, static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,
uint32_t ctx_id); uint32_t ctx_id);
@ -1568,7 +1596,8 @@ static const vrend_decode_callback decode_table[VIRGL_MAX_COMMANDS] = {
[VIRGL_CCMD_COPY_TRANSFER3D] = vrend_decode_copy_transfer3d, [VIRGL_CCMD_COPY_TRANSFER3D] = vrend_decode_copy_transfer3d,
[VIRGL_CCMD_END_TRANSFERS] = vrend_decode_dummy, [VIRGL_CCMD_END_TRANSFERS] = vrend_decode_dummy,
[VIRGL_CCMD_SET_TWEAKS] = vrend_decode_set_tweaks, [VIRGL_CCMD_SET_TWEAKS] = vrend_decode_set_tweaks,
[VIRGL_CCMD_PIPE_RESOURCE_CREATE] = vrend_decode_pipe_resource_create [VIRGL_CCMD_PIPE_RESOURCE_CREATE] = vrend_decode_pipe_resource_create,
[VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE] = vrend_decode_pipe_resource_set_type,
}; };
static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx, static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx,

@ -706,8 +706,9 @@ struct vrend_context {
* *
* It is however possible that we encounter untyped virgl_resources that * It is however possible that we encounter untyped virgl_resources that
* have no pipe_resources. To work with untyped virgl_resources, we park * have no pipe_resources. To work with untyped virgl_resources, we park
* them in untyped_resources first when they are attached. TODO: create * them in untyped_resources first when they are attached. We move them
* vrend_resources after we get the type information. * into res_hash only after we get the type information and create the
* vrend_resources in vrend_decode_pipe_resource_set_type.
*/ */
struct list_head untyped_resources; struct list_head untyped_resources;
struct virgl_resource *untyped_resource_cache; struct virgl_resource *untyped_resource_cache;
@ -10272,6 +10273,11 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c
if (has_feature(feat_blend_equation_advanced)) if (has_feature(feat_blend_equation_advanced))
caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_BLEND_EQUATION; caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_BLEND_EQUATION;
#ifdef HAVE_EPOXY_EGL_H
if (egl)
caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_UNTYPED_RESOURCE;
#endif
} }
void vrend_renderer_fill_caps(uint32_t set, uint32_t version, void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
@ -10466,6 +10472,7 @@ void vrend_renderer_attach_res_ctx(struct vrend_context *ctx,
} }
ctx->untyped_resource_cache = res; ctx->untyped_resource_cache = res;
/* defer to vrend_renderer_pipe_resource_set_type */
return; return;
} }
@ -10740,6 +10747,122 @@ struct pipe_resource *vrend_get_blob_pipe(struct vrend_context *ctx, uint64_t bl
return NULL; return NULL;
} }
int
vrend_renderer_pipe_resource_set_type(struct vrend_context *ctx,
uint32_t res_id,
const struct vrend_renderer_resource_set_type_args *args)
{
struct virgl_resource *res = NULL;
/* look up the untyped resource */
if (ctx->untyped_resource_cache &&
ctx->untyped_resource_cache->res_id == res_id) {
res = ctx->untyped_resource_cache;
ctx->untyped_resource_cache = NULL;
} else {
/* cache miss */
struct vrend_untyped_resource *iter;
LIST_FOR_EACH_ENTRY(iter, &ctx->untyped_resources, head) {
if (iter->resource->res_id == res_id) {
res = iter->resource;
list_del(&iter->head);
free(iter);
break;
}
}
}
/* either a bad res_id or the resource is already typed */
if (!res) {
if (vrend_renderer_ctx_res_lookup(ctx, res_id))
return 0;
vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_id);
return EINVAL;
}
/* resource is still untyped */
if (!res->pipe_resource) {
#ifdef HAVE_EPOXY_EGL_H
const struct vrend_renderer_resource_create_args create_args = {
.target = PIPE_TEXTURE_2D,
.format = args->format,
.bind = args->bind,
.width = args->width,
.height = args->height,
.depth = 1,
.array_size = 1,
.last_level = 0,
.nr_samples = 0,
.flags = 0,
};
int plane_fds[VIRGL_GBM_MAX_PLANES];
struct vrend_resource *gr;
uint32_t virgl_format;
uint32_t drm_format;
int ret;
if (res->fd_type != VIRGL_RESOURCE_FD_DMABUF)
return EINVAL;
for (uint32_t i = 0; i < args->plane_count; i++)
plane_fds[i] = res->fd;
gr = vrend_resource_create(&create_args);
if (!gr)
return ENOMEM;
virgl_format = vrend_resource_fixup_emulated_bgra(gr, true);
drm_format = 0;
if (virgl_gbm_convert_format(&virgl_format, &drm_format)) {
vrend_printf("%s: unsupported format %d\n", __func__, virgl_format);
FREE(gr);
return EINVAL;
}
gr->egl_image = virgl_egl_image_from_dmabuf(egl,
args->width,
args->height,
drm_format,
args->modifier,
args->plane_count,
plane_fds,
args->plane_strides,
args->plane_offsets);
if (!gr->egl_image) {
vrend_printf("%s: failed to create egl image\n", __func__);
FREE(gr);
return EINVAL;
}
gr->storage_bits |= VREND_STORAGE_EGL_IMAGE;
ret = vrend_resource_alloc_texture(gr, virgl_format, gr->egl_image);
if (ret) {
virgl_egl_image_destroy(egl, gr->egl_image);
FREE(gr);
return ret;
}
/* "promote" the fd to pipe_resource */
close(res->fd);
res->fd = -1;
res->fd_type = VIRGL_RESOURCE_FD_INVALID;
res->pipe_resource = &gr->base;
#else /* HAVE_EPOXY_EGL_H */
(void)args;
vrend_printf("%s: no EGL support \n", __func__);
return EINVAL;
#endif /* HAVE_EPOXY_EGL_H */
}
vrend_ctx_resource_insert(ctx->res_hash,
res->res_id,
(struct vrend_resource *)res->pipe_resource);
return 0;
}
uint32_t vrend_renderer_resource_get_map_info(struct pipe_resource *pres) uint32_t vrend_renderer_resource_get_map_info(struct pipe_resource *pres)
{ {
struct vrend_resource *res = (struct vrend_resource *)pres; struct vrend_resource *res = (struct vrend_resource *)pres;

@ -186,6 +186,19 @@ struct vrend_renderer_resource_create_args {
uint32_t flags; uint32_t flags;
}; };
/* set the type info of an untyped blob resource */
struct vrend_renderer_resource_set_type_args {
uint32_t format;
uint32_t bind;
uint32_t width;
uint32_t height;
uint32_t usage;
uint64_t modifier;
uint32_t plane_count;
uint32_t plane_strides[VIRGL_GBM_MAX_PLANES];
uint32_t plane_offsets[VIRGL_GBM_MAX_PLANES];
};
struct pipe_resource * struct pipe_resource *
vrend_renderer_resource_create(const struct vrend_renderer_resource_create_args *args, vrend_renderer_resource_create(const struct vrend_renderer_resource_create_args *args,
void *image_eos); void *image_eos);
@ -491,6 +504,11 @@ 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); struct pipe_resource *vrend_get_blob_pipe(struct vrend_context *ctx, uint64_t blob_id);
int
vrend_renderer_pipe_resource_set_type(struct vrend_context *ctx,
uint32_t res_id,
const struct vrend_renderer_resource_set_type_args *args);
uint32_t vrend_renderer_resource_get_map_info(struct pipe_resource *pres); uint32_t vrend_renderer_resource_get_map_info(struct pipe_resource *pres);
int vrend_renderer_resource_map(struct pipe_resource *pres, void **map, uint64_t *out_size); int vrend_renderer_resource_map(struct pipe_resource *pres, void **map, uint64_t *out_size);

Loading…
Cancel
Save