aboutsummaryrefslogtreecommitdiff
path: root/vtest/vtest_renderer.c
diff options
context:
space:
mode:
Diffstat (limited to 'vtest/vtest_renderer.c')
-rw-r--r--vtest/vtest_renderer.c164
1 files changed, 152 insertions, 12 deletions
diff --git a/vtest/vtest_renderer.c b/vtest/vtest_renderer.c
index 58631c97..61e81e4b 100644
--- a/vtest/vtest_renderer.c
+++ b/vtest/vtest_renderer.c
@@ -61,7 +61,11 @@ struct vtest_context {
struct vtest_input *input;
int out_fd;
+ char *debug_name;
+
unsigned protocol_version;
+ unsigned capset_id;
+ bool context_initialized;
struct util_hash_table *resource_table;
};
@@ -278,9 +282,7 @@ void vtest_cleanup_renderer(void)
struct vtest_context *ctx, *tmp;
LIST_FOR_EACH_ENTRY_SAFE(ctx, tmp, &renderer.active_contexts, head) {
- virgl_renderer_context_destroy(ctx->ctx_id);
- util_hash_table_clear(ctx->resource_table);
- vtest_free_context(ctx, true);
+ vtest_destroy_context(ctx);
}
LIST_FOR_EACH_ENTRY_SAFE(ctx, tmp, &renderer.free_contexts, head) {
vtest_free_context(ctx, true);
@@ -323,8 +325,11 @@ static struct vtest_context *vtest_new_context(struct vtest_input *input,
ctx->input = input;
ctx->out_fd = out_fd;
+ ctx->debug_name = NULL;
/* By default we support version 0 unless VCMD_PROTOCOL_VERSION is sent */
ctx->protocol_version = 0;
+ ctx->capset_id = 0;
+ ctx->context_initialized = false;
return ctx;
}
@@ -358,26 +363,46 @@ int vtest_create_context(struct vtest_input *input, int out_fd,
vtestname = calloc(1, length + 1);
if (!vtestname) {
ret = -1;
- goto end;
+ goto err;
}
ret = ctx->input->read(ctx->input, vtestname, length);
if (ret != (int)length) {
ret = -1;
- goto end;
+ goto err;
}
- ret = virgl_renderer_context_create(ctx->ctx_id, strlen(vtestname), vtestname);
+ ctx->debug_name = vtestname;
-end:
+ list_addtail(&ctx->head, &renderer.active_contexts);
+ *out_ctx = ctx;
+
+ return 0;
+
+err:
free(vtestname);
+ vtest_free_context(ctx, false);
+ return ret;
+}
- if (ret) {
- vtest_free_context(ctx, false);
+int vtest_lazy_init_context(struct vtest_context *ctx)
+{
+ int ret;
+
+ if (ctx->context_initialized)
+ return 0;
+
+ if (ctx->capset_id) {
+ ret = virgl_renderer_context_create_with_flags(ctx->ctx_id,
+ ctx->capset_id,
+ strlen(ctx->debug_name),
+ ctx->debug_name);
} else {
- list_addtail(&ctx->head, &renderer.active_contexts);
- *out_ctx = ctx;
+ ret = virgl_renderer_context_create(ctx->ctx_id,
+ strlen(ctx->debug_name),
+ ctx->debug_name);
}
+ ctx->context_initialized = (ret == 0);
return ret;
}
@@ -389,7 +414,9 @@ void vtest_destroy_context(struct vtest_context *ctx)
}
list_del(&ctx->head);
- virgl_renderer_context_destroy(ctx->ctx_id);
+ free(ctx->debug_name);
+ if (ctx->context_initialized)
+ virgl_renderer_context_destroy(ctx->ctx_id);
util_hash_table_clear(ctx->resource_table);
vtest_free_context(ctx, false);
}
@@ -471,6 +498,111 @@ int vtest_protocol_version(UNUSED uint32_t length_dw)
return 0;
}
+int vtest_get_param(UNUSED uint32_t length_dw)
+{
+ struct vtest_context *ctx = vtest_get_current_context();
+ uint32_t get_param_buf[VCMD_GET_PARAM_SIZE];
+ uint32_t resp_buf[VTEST_HDR_SIZE + 2];
+ uint32_t param;
+ uint32_t *resp;
+ int ret;
+
+ ret = ctx->input->read(ctx->input, get_param_buf, sizeof(get_param_buf));
+ if (ret != sizeof(get_param_buf))
+ return -1;
+
+ param = get_param_buf[VCMD_GET_PARAM_PARAM];
+
+ resp_buf[VTEST_CMD_LEN] = 2;
+ resp_buf[VTEST_CMD_ID] = VCMD_GET_PARAM;
+ resp = &resp_buf[VTEST_CMD_DATA_START];
+ switch (param) {
+ default:
+ resp[0] = false;
+ resp[1] = 0;
+ break;
+ }
+
+ ret = vtest_block_write(ctx->out_fd, resp_buf, sizeof(resp_buf));
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+int vtest_get_capset(UNUSED uint32_t length_dw)
+{
+ struct vtest_context *ctx = vtest_get_current_context();
+ uint32_t get_capset_buf[VCMD_GET_CAPSET_SIZE];
+ uint32_t resp_buf[VTEST_HDR_SIZE + 1];
+ uint32_t id;
+ uint32_t version;
+ uint32_t max_version;
+ uint32_t max_size;
+ void *caps;
+ int ret;
+
+ ret = ctx->input->read(ctx->input, get_capset_buf, sizeof(get_capset_buf));
+ if (ret != sizeof(get_capset_buf))
+ return -1;
+
+ id = get_capset_buf[VCMD_GET_CAPSET_ID];
+ version = get_capset_buf[VCMD_GET_CAPSET_VERSION];
+
+ virgl_renderer_get_cap_set(id, &max_version, &max_size);
+
+ /* unsupported id or version */
+ if ((!max_version && !max_size) || version > max_version) {
+ resp_buf[VTEST_CMD_LEN] = 1;
+ resp_buf[VTEST_CMD_ID] = VCMD_GET_CAPSET;
+ resp_buf[VTEST_CMD_DATA_START] = false;
+ return vtest_block_write(ctx->out_fd, resp_buf, sizeof(resp_buf));
+ }
+
+ if (max_size % 4)
+ return -EINVAL;
+
+ caps = malloc(max_size);
+ if (!caps)
+ return -ENOMEM;
+
+ virgl_renderer_fill_caps(id, version, caps);
+
+ resp_buf[VTEST_CMD_LEN] = 1 + max_size / 4;
+ resp_buf[VTEST_CMD_ID] = VCMD_GET_CAPSET;
+ resp_buf[VTEST_CMD_DATA_START] = true;
+ ret = vtest_block_write(ctx->out_fd, resp_buf, sizeof(resp_buf));
+ if (ret >= 0)
+ ret = vtest_block_write(ctx->out_fd, caps, max_size);
+
+ free(caps);
+ return ret >= 0 ? 0 : ret;
+}
+
+int vtest_context_init(UNUSED uint32_t length_dw)
+{
+ struct vtest_context *ctx = vtest_get_current_context();
+ uint32_t context_init_buf[VCMD_CONTEXT_INIT_SIZE];
+ uint32_t capset_id;
+ int ret;
+
+ ret = ctx->input->read(ctx->input, context_init_buf, sizeof(context_init_buf));
+ if (ret != sizeof(context_init_buf))
+ return -1;
+
+ capset_id = context_init_buf[VCMD_CONTEXT_INIT_CAPSET_ID];
+ if (!capset_id)
+ return -EINVAL;
+
+ if (ctx->context_initialized) {
+ return ctx->capset_id == capset_id ? 0 : -EINVAL;
+ }
+
+ ctx->capset_id = capset_id;
+
+ return vtest_lazy_init_context(ctx);
+}
+
int vtest_send_caps2(UNUSED uint32_t length_dw)
{
struct vtest_context *ctx = vtest_get_current_context();
@@ -1054,6 +1186,14 @@ int vtest_resource_busy_wait(UNUSED uint32_t length_dw)
return -1;
}
+ /* clients often send VCMD_PING_PROTOCOL_VERSION followed by
+ * VCMD_RESOURCE_BUSY_WAIT with handle 0 to figure out if
+ * VCMD_PING_PROTOCOL_VERSION is supported. We need to make a special case
+ * for that.
+ */
+ if (!ctx->context_initialized && bw_buf[VCMD_BUSY_WAIT_HANDLE])
+ return -1;
+
/* handle = bw_buf[VCMD_BUSY_WAIT_HANDLE]; unused as of now */
flags = bw_buf[VCMD_BUSY_WAIT_FLAGS];