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

Loading…
Cancel
Save