vrend: reduce work done in command decoding loop

v2: drop decode state and use local variables to handle keeping
    track of the decode buffer state (Chia-I Wo)

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
macos/master
Gert Wollny 4 years ago
parent cbcba9845f
commit 569ea169ba
  1. 51
      src/vrend_decode.c

@ -44,16 +44,8 @@
/* decode side */
#define DECODE_MAX_TOKENS 8000
struct vrend_decoder_state {
const uint32_t *buf;
uint32_t buf_total;
uint32_t buf_offset;
};
struct vrend_decode_ctx {
struct virgl_context base;
struct vrend_decoder_state ids, *ds;
struct vrend_context *grctx;
};
@ -1467,8 +1459,6 @@ struct virgl_context *vrend_renderer_context_create(uint32_t handle,
return NULL;
}
dctx->ds = &dctx->ids;
return &dctx->base;
}
@ -1603,42 +1593,45 @@ static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx,
if (bret == false)
return EINVAL;
gdctx->ds->buf = buffer;
gdctx->ds->buf_total = size / sizeof(uint32_t);
gdctx->ds->buf_offset = 0;
const uint32_t *typed_buf = (const uint32_t *)buffer;
const uint32_t buf_total = size / sizeof(uint32_t);
uint32_t buf_offset = 0;
while (gdctx->ds->buf_offset < gdctx->ds->buf_total) {
uint32_t header = gdctx->ds->buf[gdctx->ds->buf_offset];
uint32_t len = header >> 16;
uint32_t cmd = header & 0xff;
while (buf_offset < buf_total) {
#ifndef NDEBUG
const uint32_t cur_offset = buf_offset;
#endif
const uint32_t *buf = &typed_buf[buf_offset];
uint32_t len = *buf >> 16;
uint32_t cmd = *buf & 0xff;
if (cmd >= VIRGL_MAX_COMMANDS)
return EINVAL;
buf_offset += len + 1;
ret = 0;
/* check if the guest is doing something bad */
if (gdctx->ds->buf_offset + len + 1 > gdctx->ds->buf_total) {
if (buf_offset > buf_total) {
vrend_report_buffer_error(gdctx->grctx, 0);
break;
}
VREND_DEBUG(dbg_cmd, gdctx->grctx,"%-4d %-20s len:%d\n",
gdctx->ds->buf_offset, vrend_get_comand_name(header & 0xff), len);
cur_offset, vrend_get_comand_name(cmd), len);
TRACE_SCOPE("%s", vrend_get_comand_name(header & 0xff));
TRACE_SCOPE("%s", vrend_get_comand_name(cmd));
ret = decode_table[cmd](gdctx, &gdctx->ds->buf[gdctx->ds->buf_offset], len);
if (ret == EINVAL) {
vrend_report_buffer_error(gdctx->grctx, header);
goto out;
ret = decode_table[cmd](gdctx, buf, len);
if (ret) {
if (ret == EINVAL) {
vrend_report_buffer_error(gdctx->grctx, *buf);
return ret;
}
}
if (ret == ENOMEM)
goto out;
gdctx->ds->buf_offset += (len) + 1;
}
return 0;
out:
return ret;
}
static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,

Loading…
Cancel
Save