diff --git a/vtest/vtest.h b/vtest/vtest.h index 15db9be..d05e292 100644 --- a/vtest/vtest.h +++ b/vtest/vtest.h @@ -80,6 +80,7 @@ int vtest_protocol_version(uint32_t length_dw); /* since protocol version 3 */ int vtest_get_param(uint32_t length_dw); +int vtest_get_capset(uint32_t length_dw); void vtest_set_max_length(uint32_t length); diff --git a/vtest/vtest_protocol.h b/vtest/vtest_protocol.h index a83339e..07df4be 100644 --- a/vtest/vtest_protocol.h +++ b/vtest/vtest_protocol.h @@ -67,6 +67,7 @@ #ifdef VIRGL_RENDERER_UNSTABLE_APIS /* since protocol version 3 */ #define VCMD_GET_PARAM 15 +#define VCMD_GET_CAPSET 16 #endif /* VIRGL_RENDERER_UNSTABLE_APIS */ #define VCMD_RES_CREATE_SIZE 10 @@ -139,6 +140,11 @@ #define VCMD_GET_PARAM_PARAM 0 /* resp param validity and value */ +#define VCMD_GET_CAPSET_SIZE 2 +#define VCMD_GET_CAPSET_ID 0 +#define VCMD_GET_CAPSET_VERSION 1 +/* resp capset validity and contents */ + #endif /* VIRGL_RENDERER_UNSTABLE_APIS */ #endif /* VTEST_PROTOCOL */ diff --git a/vtest/vtest_renderer.c b/vtest/vtest_renderer.c index ff6d6a5..16c053a 100644 --- a/vtest/vtest_renderer.c +++ b/vtest/vtest_renderer.c @@ -521,6 +521,55 @@ int vtest_get_param(UNUSED uint32_t length_dw) 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_send_caps2(UNUSED uint32_t length_dw) { struct vtest_context *ctx = vtest_get_current_context(); diff --git a/vtest/vtest_server.c b/vtest/vtest_server.c index 866224c..2e5689f 100644 --- a/vtest/vtest_server.c +++ b/vtest/vtest_server.c @@ -606,6 +606,7 @@ static const struct vtest_command { /* since protocol version 3 */ [VCMD_GET_PARAM] = { vtest_get_param, false }, + [VCMD_GET_CAPSET] = { vtest_get_capset, false }, }; static int vtest_client_dispatch_commands(struct vtest_client *client)