Home | History | Annotate | Download | only in src
      1 /**************************************************************************
      2  *
      3  * Copyright (C) 2014 Red Hat Inc.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be included
     13  * in all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     21  * OTHER DEALINGS IN THE SOFTWARE.
     22  *
     23  **************************************************************************/
     24 #include <stdint.h>
     25 #include <string.h>
     26 #include <stdio.h>
     27 #include <errno.h>
     28 #include <epoxy/gl.h>
     29 
     30 #include "util/u_memory.h"
     31 #include "pipe/p_state.h"
     32 #include "pipe/p_shader_tokens.h"
     33 #include "vrend_renderer.h"
     34 #include "vrend_object.h"
     35 #include "tgsi/tgsi_text.h"
     36 
     37 /* decode side */
     38 #define DECODE_MAX_TOKENS 8000
     39 
     40 struct vrend_decoder_state {
     41    uint32_t *buf;
     42    uint32_t buf_total;
     43    uint32_t buf_offset;
     44 };
     45 
     46 struct vrend_decode_ctx {
     47    struct vrend_decoder_state ids, *ds;
     48    struct vrend_context *grctx;
     49 };
     50 #define VREND_MAX_CTX 64
     51 static struct vrend_decode_ctx *dec_ctx[VREND_MAX_CTX];
     52 
     53 static inline uint32_t get_buf_entry(struct vrend_decode_ctx *ctx, uint32_t offset)
     54 {
     55    return ctx->ds->buf[ctx->ds->buf_offset + offset];
     56 }
     57 
     58 static inline void *get_buf_ptr(struct vrend_decode_ctx *ctx,
     59                                 uint32_t offset)
     60 {
     61    return &ctx->ds->buf[ctx->ds->buf_offset + offset];
     62 }
     63 
     64 static int vrend_decode_create_shader(struct vrend_decode_ctx *ctx,
     65                                       uint32_t handle,
     66                                       uint16_t length)
     67 {
     68    struct pipe_stream_output_info so_info;
     69    uint i;
     70    int ret;
     71    uint32_t shader_offset, req_local_mem = 0;
     72    unsigned num_tokens, num_so_outputs, offlen;
     73    uint8_t *shd_text;
     74    uint32_t type;
     75 
     76    if (length < VIRGL_OBJ_SHADER_HDR_SIZE(0))
     77       return EINVAL;
     78 
     79    type = get_buf_entry(ctx, VIRGL_OBJ_SHADER_TYPE);
     80    num_tokens = get_buf_entry(ctx, VIRGL_OBJ_SHADER_NUM_TOKENS);
     81    offlen = get_buf_entry(ctx, VIRGL_OBJ_SHADER_OFFSET);
     82 
     83    if (type == PIPE_SHADER_COMPUTE) {
     84       req_local_mem = get_buf_entry(ctx, VIRGL_OBJ_SHADER_SO_NUM_OUTPUTS);
     85       num_so_outputs = 0;
     86    } else {
     87       num_so_outputs = get_buf_entry(ctx, VIRGL_OBJ_SHADER_SO_NUM_OUTPUTS);
     88       if (length < VIRGL_OBJ_SHADER_HDR_SIZE(num_so_outputs))
     89          return EINVAL;
     90 
     91       if (num_so_outputs > PIPE_MAX_SO_OUTPUTS)
     92          return EINVAL;
     93    }
     94 
     95    shader_offset = 6;
     96    if (num_so_outputs) {
     97       so_info.num_outputs = num_so_outputs;
     98       if (so_info.num_outputs) {
     99          for (i = 0; i < 4; i++)
    100             so_info.stride[i] = get_buf_entry(ctx, VIRGL_OBJ_SHADER_SO_STRIDE(i));
    101          for (i = 0; i < so_info.num_outputs; i++) {
    102             uint32_t tmp = get_buf_entry(ctx, VIRGL_OBJ_SHADER_SO_OUTPUT0(i));
    103 
    104             so_info.output[i].register_index = tmp & 0xff;
    105             so_info.output[i].start_component = (tmp >> 8) & 0x3;
    106             so_info.output[i].num_components = (tmp >> 10) & 0x7;
    107             so_info.output[i].output_buffer = (tmp >> 13) & 0x7;
    108             so_info.output[i].dst_offset = (tmp >> 16) & 0xffff;
    109             tmp = get_buf_entry(ctx, VIRGL_OBJ_SHADER_SO_OUTPUT0_SO(i));
    110             so_info.output[i].stream = (tmp & 0x3);
    111          }
    112       }
    113       shader_offset += 4 + (2 * num_so_outputs);
    114    } else
    115      memset(&so_info, 0, sizeof(so_info));
    116 
    117    shd_text = get_buf_ptr(ctx, shader_offset);
    118    ret = vrend_create_shader(ctx->grctx, handle, &so_info, req_local_mem, (const char *)shd_text, offlen, num_tokens, type, length - shader_offset + 1);
    119 
    120    return ret;
    121 }
    122 
    123 static int vrend_decode_create_stream_output_target(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
    124 {
    125    uint32_t res_handle, buffer_size, buffer_offset;
    126 
    127    if (length != VIRGL_OBJ_STREAMOUT_SIZE)
    128       return EINVAL;
    129 
    130    res_handle = get_buf_entry(ctx, VIRGL_OBJ_STREAMOUT_RES_HANDLE);
    131    buffer_offset = get_buf_entry(ctx, VIRGL_OBJ_STREAMOUT_BUFFER_OFFSET);
    132    buffer_size = get_buf_entry(ctx, VIRGL_OBJ_STREAMOUT_BUFFER_SIZE);
    133 
    134    return vrend_create_so_target(ctx->grctx, handle, res_handle, buffer_offset,
    135                                  buffer_size);
    136 }
    137 
    138 static int vrend_decode_set_framebuffer_state(struct vrend_decode_ctx *ctx, int length)
    139 {
    140    if (length < 2)
    141       return EINVAL;
    142 
    143    int32_t nr_cbufs = get_buf_entry(ctx, VIRGL_SET_FRAMEBUFFER_STATE_NR_CBUFS);
    144    uint32_t zsurf_handle = get_buf_entry(ctx, VIRGL_SET_FRAMEBUFFER_STATE_NR_ZSURF_HANDLE);
    145    uint32_t surf_handle[8];
    146    int i;
    147 
    148    if (length != (2 + nr_cbufs))
    149       return EINVAL;
    150 
    151    if (nr_cbufs > 8)
    152       return EINVAL;
    153 
    154    for (i = 0; i < nr_cbufs; i++)
    155       surf_handle[i] = get_buf_entry(ctx, VIRGL_SET_FRAMEBUFFER_STATE_CBUF_HANDLE(i));
    156    vrend_set_framebuffer_state(ctx->grctx, nr_cbufs, surf_handle, zsurf_handle);
    157    return 0;
    158 }
    159 
    160 static int vrend_decode_set_framebuffer_state_no_attach(struct vrend_decode_ctx *ctx, int length)
    161 {
    162    uint32_t width, height;
    163    uint32_t layers, samples;
    164    uint32_t tmp;
    165 
    166    if (length != VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_SIZE)
    167       return EINVAL;
    168 
    169    tmp = get_buf_entry(ctx, VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_WIDTH_HEIGHT);
    170    width = VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_WIDTH(tmp);
    171    height = VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_HEIGHT(tmp);
    172 
    173    tmp = get_buf_entry(ctx, VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_LAYERS_SAMPLES);
    174    layers = VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_LAYERS(tmp);
    175    samples = VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_SAMPLES(tmp);
    176 
    177    vrend_set_framebuffer_state_no_attach(ctx->grctx, width, height, layers, samples);
    178    return 0;
    179 }
    180 
    181 static int vrend_decode_clear(struct vrend_decode_ctx *ctx, int length)
    182 {
    183    union pipe_color_union color;
    184    double depth;
    185    unsigned stencil, buffers;
    186    int i;
    187 
    188    if (length != VIRGL_OBJ_CLEAR_SIZE)
    189       return EINVAL;
    190    buffers = get_buf_entry(ctx, VIRGL_OBJ_CLEAR_BUFFERS);
    191    for (i = 0; i < 4; i++)
    192       color.ui[i] = get_buf_entry(ctx, VIRGL_OBJ_CLEAR_COLOR_0 + i);
    193    depth = *(double *)(uint64_t *)get_buf_ptr(ctx, VIRGL_OBJ_CLEAR_DEPTH_0);
    194    stencil = get_buf_entry(ctx, VIRGL_OBJ_CLEAR_STENCIL);
    195 
    196    vrend_clear(ctx->grctx, buffers, &color, depth, stencil);
    197    return 0;
    198 }
    199 
    200 static float uif(unsigned int ui)
    201 {
    202    union { float f; unsigned int ui; } myuif;
    203    myuif.ui = ui;
    204    return myuif.f;
    205 }
    206 
    207 static int vrend_decode_set_viewport_state(struct vrend_decode_ctx *ctx, int length)
    208 {
    209    struct pipe_viewport_state vps[PIPE_MAX_VIEWPORTS];
    210    uint i, v;
    211    uint32_t num_viewports, start_slot;
    212    if (length < 1)
    213       return EINVAL;
    214 
    215    if ((length - 1) % 6)
    216       return EINVAL;
    217 
    218    num_viewports = (length - 1) / 6;
    219    start_slot = get_buf_entry(ctx, VIRGL_SET_VIEWPORT_START_SLOT);
    220 
    221    if (num_viewports > PIPE_MAX_VIEWPORTS ||
    222        start_slot > (PIPE_MAX_VIEWPORTS - num_viewports))
    223       return EINVAL;
    224 
    225    for (v = 0; v < num_viewports; v++) {
    226       for (i = 0; i < 3; i++)
    227          vps[v].scale[i] = uif(get_buf_entry(ctx, VIRGL_SET_VIEWPORT_STATE_SCALE_0(v) + i));
    228       for (i = 0; i < 3; i++)
    229          vps[v].translate[i] = uif(get_buf_entry(ctx, VIRGL_SET_VIEWPORT_STATE_TRANSLATE_0(v) + i));
    230    }
    231 
    232    vrend_set_viewport_states(ctx->grctx, start_slot, num_viewports, vps);
    233    return 0;
    234 }
    235 
    236 static int vrend_decode_set_index_buffer(struct vrend_decode_ctx *ctx, int length)
    237 {
    238    if (length != 1 && length != 3)
    239       return EINVAL;
    240    vrend_set_index_buffer(ctx->grctx,
    241                           get_buf_entry(ctx, VIRGL_SET_INDEX_BUFFER_HANDLE),
    242                           (length == 3) ? get_buf_entry(ctx, VIRGL_SET_INDEX_BUFFER_INDEX_SIZE) : 0,
    243                           (length == 3) ? get_buf_entry(ctx, VIRGL_SET_INDEX_BUFFER_OFFSET) : 0);
    244    return 0;
    245 }
    246 
    247 static int vrend_decode_set_constant_buffer(struct vrend_decode_ctx *ctx, uint16_t length)
    248 {
    249    uint32_t shader;
    250    uint32_t index;
    251    int nc = (length - 2);
    252 
    253    if (length < 2)
    254       return EINVAL;
    255 
    256    shader = get_buf_entry(ctx, VIRGL_SET_CONSTANT_BUFFER_SHADER_TYPE);
    257    index = get_buf_entry(ctx, VIRGL_SET_CONSTANT_BUFFER_INDEX);
    258 
    259    if (shader >= PIPE_SHADER_TYPES)
    260       return EINVAL;
    261 
    262    vrend_set_constants(ctx->grctx, shader, index, nc, get_buf_ptr(ctx, VIRGL_SET_CONSTANT_BUFFER_DATA_START));
    263    return 0;
    264 }
    265 
    266 static int vrend_decode_set_uniform_buffer(struct vrend_decode_ctx *ctx, int length)
    267 {
    268    if (length != VIRGL_SET_UNIFORM_BUFFER_SIZE)
    269       return EINVAL;
    270 
    271    uint32_t shader = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_SHADER_TYPE);
    272    uint32_t index = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_INDEX);
    273    uint32_t offset = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_OFFSET);
    274    uint32_t blength = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_LENGTH);
    275    uint32_t handle = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_RES_HANDLE);
    276 
    277    if (shader >= PIPE_SHADER_TYPES)
    278       return EINVAL;
    279 
    280    if (index >= PIPE_MAX_CONSTANT_BUFFERS)
    281       return EINVAL;
    282 
    283    vrend_set_uniform_buffer(ctx->grctx, shader, index, offset, blength, handle);
    284    return 0;
    285 }
    286 
    287 static int vrend_decode_set_vertex_buffers(struct vrend_decode_ctx *ctx, uint16_t length)
    288 {
    289    int num_vbo;
    290    int i;
    291 
    292    /* must be a multiple of 3 */
    293    if (length && (length % 3))
    294       return EINVAL;
    295 
    296    num_vbo = (length / 3);
    297    if (num_vbo > PIPE_MAX_ATTRIBS)
    298       return EINVAL;
    299 
    300    for (i = 0; i < num_vbo; i++) {
    301       vrend_set_single_vbo(ctx->grctx, i,
    302                            get_buf_entry(ctx, VIRGL_SET_VERTEX_BUFFER_STRIDE(i)),
    303                            get_buf_entry(ctx, VIRGL_SET_VERTEX_BUFFER_OFFSET(i)),
    304                            get_buf_entry(ctx, VIRGL_SET_VERTEX_BUFFER_HANDLE(i)));
    305    }
    306    vrend_set_num_vbo(ctx->grctx, num_vbo);
    307    return 0;
    308 }
    309 
    310 static int vrend_decode_set_sampler_views(struct vrend_decode_ctx *ctx, uint16_t length)
    311 {
    312    uint32_t num_samps;
    313    uint32_t i;
    314    uint32_t shader_type;
    315    uint32_t start_slot;
    316 
    317    if (length < 2)
    318       return EINVAL;
    319    num_samps = length - 2;
    320    shader_type = get_buf_entry(ctx, VIRGL_SET_SAMPLER_VIEWS_SHADER_TYPE);
    321    start_slot = get_buf_entry(ctx, VIRGL_SET_SAMPLER_VIEWS_START_SLOT);
    322 
    323    if (shader_type >= PIPE_SHADER_TYPES)
    324       return EINVAL;
    325 
    326    if (num_samps > PIPE_MAX_SHADER_SAMPLER_VIEWS ||
    327        start_slot > (PIPE_MAX_SHADER_SAMPLER_VIEWS - num_samps))
    328       return EINVAL;
    329 
    330    for (i = 0; i < num_samps; i++) {
    331       uint32_t handle = get_buf_entry(ctx, VIRGL_SET_SAMPLER_VIEWS_V0_HANDLE + i);
    332       vrend_set_single_sampler_view(ctx->grctx, shader_type, i + start_slot, handle);
    333    }
    334    vrend_set_num_sampler_views(ctx->grctx, shader_type, start_slot, num_samps);
    335    return 0;
    336 }
    337 
    338 static int vrend_decode_resource_inline_write(struct vrend_decode_ctx *ctx, uint16_t length)
    339 {
    340    struct vrend_transfer_info info;
    341    struct pipe_box box;
    342    uint32_t res_handle;
    343    uint32_t level, usage, stride, layer_stride, data_len;
    344    struct iovec dataiovec;
    345    void *data;
    346 
    347    if (length < 12)
    348       return EINVAL;
    349 
    350    if (length + ctx->ds->buf_offset > ctx->ds->buf_total)
    351       return EINVAL;
    352 
    353    res_handle = get_buf_entry(ctx, VIRGL_RESOURCE_IW_RES_HANDLE);
    354    data_len = (length - 11) * 4;
    355    level = get_buf_entry(ctx, VIRGL_RESOURCE_IW_LEVEL);
    356    usage = get_buf_entry(ctx, VIRGL_RESOURCE_IW_USAGE);
    357    stride = get_buf_entry(ctx, VIRGL_RESOURCE_IW_STRIDE);
    358    layer_stride = get_buf_entry(ctx, VIRGL_RESOURCE_IW_LAYER_STRIDE);
    359    box.x = get_buf_entry(ctx, VIRGL_RESOURCE_IW_X);
    360    box.y = get_buf_entry(ctx, VIRGL_RESOURCE_IW_Y);
    361    box.z = get_buf_entry(ctx, VIRGL_RESOURCE_IW_Z);
    362    box.width = get_buf_entry(ctx, VIRGL_RESOURCE_IW_W);
    363    box.height = get_buf_entry(ctx, VIRGL_RESOURCE_IW_H);
    364    box.depth = get_buf_entry(ctx, VIRGL_RESOURCE_IW_D);
    365 
    366    data = get_buf_ptr(ctx, VIRGL_RESOURCE_IW_DATA_START);
    367 
    368    info.handle = res_handle;
    369    info.ctx_id = 0;
    370    info.level = level;
    371    info.stride = stride;
    372    info.layer_stride = layer_stride;
    373    info.box = &box;
    374    info.offset = 0;
    375 
    376    dataiovec.iov_base = data;
    377    dataiovec.iov_len = data_len;
    378 
    379    info.iovec = &dataiovec;
    380    info.iovec_cnt = 1;
    381    return vrend_transfer_inline_write(ctx->grctx, &info, usage);
    382 }
    383 
    384 static int vrend_decode_draw_vbo(struct vrend_decode_ctx *ctx, int length)
    385 {
    386    struct pipe_draw_info info;
    387    uint32_t cso;
    388    uint32_t handle = 0, indirect_draw_count_handle = 0;
    389    if (length != VIRGL_DRAW_VBO_SIZE && length != VIRGL_DRAW_VBO_SIZE_TESS &&
    390        length != VIRGL_DRAW_VBO_SIZE_INDIRECT)
    391       return EINVAL;
    392    memset(&info, 0, sizeof(struct pipe_draw_info));
    393 
    394    info.start = get_buf_entry(ctx, VIRGL_DRAW_VBO_START);
    395    info.count = get_buf_entry(ctx, VIRGL_DRAW_VBO_COUNT);
    396    info.mode = get_buf_entry(ctx, VIRGL_DRAW_VBO_MODE);
    397    info.indexed = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDEXED);
    398    info.instance_count = get_buf_entry(ctx, VIRGL_DRAW_VBO_INSTANCE_COUNT);
    399    info.index_bias = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDEX_BIAS);
    400    info.start_instance = get_buf_entry(ctx, VIRGL_DRAW_VBO_START_INSTANCE);
    401    info.primitive_restart = get_buf_entry(ctx, VIRGL_DRAW_VBO_PRIMITIVE_RESTART);
    402    info.restart_index = get_buf_entry(ctx, VIRGL_DRAW_VBO_RESTART_INDEX);
    403    info.min_index = get_buf_entry(ctx, VIRGL_DRAW_VBO_MIN_INDEX);
    404    info.max_index = get_buf_entry(ctx, VIRGL_DRAW_VBO_MAX_INDEX);
    405 
    406    if (length >= VIRGL_DRAW_VBO_SIZE_TESS) {
    407       info.vertices_per_patch = get_buf_entry(ctx, VIRGL_DRAW_VBO_VERTICES_PER_PATCH);
    408       info.drawid = get_buf_entry(ctx, VIRGL_DRAW_VBO_DRAWID);
    409    }
    410 
    411    if (length == VIRGL_DRAW_VBO_SIZE_INDIRECT) {
    412       handle = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_HANDLE);
    413       info.indirect.offset = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_OFFSET);
    414       info.indirect.stride = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_STRIDE);
    415       info.indirect.draw_count = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT);
    416       info.indirect.indirect_draw_count_offset = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_OFFSET);
    417       indirect_draw_count_handle = get_buf_entry(ctx, VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_HANDLE);
    418    }
    419 
    420    cso = get_buf_entry(ctx, VIRGL_DRAW_VBO_COUNT_FROM_SO);
    421 
    422    return vrend_draw_vbo(ctx->grctx, &info, cso, handle, indirect_draw_count_handle);
    423 }
    424 
    425 static int vrend_decode_create_blend(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
    426 {
    427    struct pipe_blend_state *blend_state;
    428    uint32_t tmp;
    429    int i;
    430 
    431    if (length != VIRGL_OBJ_BLEND_SIZE) {
    432       return EINVAL;
    433    }
    434 
    435    blend_state = CALLOC_STRUCT(pipe_blend_state);
    436    if (!blend_state)
    437       return ENOMEM;
    438 
    439    tmp = get_buf_entry(ctx, VIRGL_OBJ_BLEND_S0);
    440    blend_state->independent_blend_enable = (tmp & 1);
    441    blend_state->logicop_enable = (tmp >> 1) & 0x1;
    442    blend_state->dither = (tmp >> 2) & 0x1;
    443    blend_state->alpha_to_coverage = (tmp >> 3) & 0x1;
    444    blend_state->alpha_to_one = (tmp >> 4) & 0x1;
    445 
    446    tmp = get_buf_entry(ctx, VIRGL_OBJ_BLEND_S1);
    447    blend_state->logicop_func = tmp & 0xf;
    448 
    449    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
    450       tmp = get_buf_entry(ctx, VIRGL_OBJ_BLEND_S2(i));
    451       blend_state->rt[i].blend_enable = tmp & 0x1;
    452       blend_state->rt[i].rgb_func = (tmp >> 1) & 0x7;
    453       blend_state->rt[i].rgb_src_factor = (tmp >> 4) & 0x1f;
    454       blend_state->rt[i].rgb_dst_factor = (tmp >> 9) & 0x1f;
    455       blend_state->rt[i].alpha_func = (tmp >> 14) & 0x7;
    456       blend_state->rt[i].alpha_src_factor = (tmp >> 17) & 0x1f;
    457       blend_state->rt[i].alpha_dst_factor = (tmp >> 22) & 0x1f;
    458       blend_state->rt[i].colormask = (tmp >> 27) & 0xf;
    459    }
    460 
    461    tmp = vrend_renderer_object_insert(ctx->grctx, blend_state, sizeof(struct pipe_blend_state), handle,
    462                                       VIRGL_OBJECT_BLEND);
    463    if (tmp == 0) {
    464       FREE(blend_state);
    465       return ENOMEM;
    466    }
    467    return 0;
    468 }
    469 
    470 static int vrend_decode_create_dsa(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
    471 {
    472    int i;
    473    struct pipe_depth_stencil_alpha_state *dsa_state;
    474    uint32_t tmp;
    475 
    476    if (length != VIRGL_OBJ_DSA_SIZE)
    477       return EINVAL;
    478 
    479    dsa_state = CALLOC_STRUCT(pipe_depth_stencil_alpha_state);
    480    if (!dsa_state)
    481       return ENOMEM;
    482 
    483    tmp = get_buf_entry(ctx, VIRGL_OBJ_DSA_S0);
    484    dsa_state->depth.enabled = tmp & 0x1;
    485    dsa_state->depth.writemask = (tmp >> 1) & 0x1;
    486    dsa_state->depth.func = (tmp >> 2) & 0x7;
    487 
    488    dsa_state->alpha.enabled = (tmp >> 8) & 0x1;
    489    dsa_state->alpha.func = (tmp >> 9) & 0x7;
    490 
    491    for (i = 0; i < 2; i++) {
    492       tmp = get_buf_entry(ctx, VIRGL_OBJ_DSA_S1 + i);
    493       dsa_state->stencil[i].enabled = tmp & 0x1;
    494       dsa_state->stencil[i].func = (tmp >> 1) & 0x7;
    495       dsa_state->stencil[i].fail_op = (tmp >> 4) & 0x7;
    496       dsa_state->stencil[i].zpass_op = (tmp >> 7) & 0x7;
    497       dsa_state->stencil[i].zfail_op = (tmp >> 10) & 0x7;
    498       dsa_state->stencil[i].valuemask = (tmp >> 13) & 0xff;
    499       dsa_state->stencil[i].writemask = (tmp >> 21) & 0xff;
    500    }
    501 
    502    tmp = get_buf_entry(ctx, VIRGL_OBJ_DSA_ALPHA_REF);
    503    dsa_state->alpha.ref_value = uif(tmp);
    504 
    505    tmp = vrend_renderer_object_insert(ctx->grctx, dsa_state, sizeof(struct pipe_depth_stencil_alpha_state), handle,
    506                                       VIRGL_OBJECT_DSA);
    507    if (tmp == 0) {
    508       FREE(dsa_state);
    509       return ENOMEM;
    510    }
    511    return 0;
    512 }
    513 
    514 static int vrend_decode_create_rasterizer(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
    515 {
    516    struct pipe_rasterizer_state *rs_state;
    517    uint32_t tmp;
    518 
    519    if (length != VIRGL_OBJ_RS_SIZE)
    520       return EINVAL;
    521 
    522    rs_state = CALLOC_STRUCT(pipe_rasterizer_state);
    523    if (!rs_state)
    524       return ENOMEM;
    525 
    526    tmp = get_buf_entry(ctx, VIRGL_OBJ_RS_S0);
    527 #define ebit(name, bit) rs_state->name = (tmp >> bit) & 0x1
    528 #define emask(name, bit, mask) rs_state->name = (tmp >> bit) & mask
    529 
    530    ebit(flatshade, 0);
    531    ebit(depth_clip, 1);
    532    ebit(clip_halfz, 2);
    533    ebit(rasterizer_discard, 3);
    534    ebit(flatshade_first, 4);
    535    ebit(light_twoside, 5);
    536    ebit(sprite_coord_mode, 6);
    537    ebit(point_quad_rasterization, 7);
    538    emask(cull_face, 8, 0x3);
    539    emask(fill_front, 10, 0x3);
    540    emask(fill_back, 12, 0x3);
    541    ebit(scissor, 14);
    542    ebit(front_ccw, 15);
    543    ebit(clamp_vertex_color, 16);
    544    ebit(clamp_fragment_color, 17);
    545    ebit(offset_line, 18);
    546    ebit(offset_point, 19);
    547    ebit(offset_tri, 20);
    548    ebit(poly_smooth, 21);
    549    ebit(poly_stipple_enable, 22);
    550    ebit(point_smooth, 23);
    551    ebit(point_size_per_vertex, 24);
    552    ebit(multisample, 25);
    553    ebit(line_smooth, 26);
    554    ebit(line_stipple_enable, 27);
    555    ebit(line_last_pixel, 28);
    556    ebit(half_pixel_center, 29);
    557    ebit(bottom_edge_rule, 30);
    558    ebit(force_persample_interp, 31);
    559    rs_state->point_size = uif(get_buf_entry(ctx, VIRGL_OBJ_RS_POINT_SIZE));
    560    rs_state->sprite_coord_enable = get_buf_entry(ctx, VIRGL_OBJ_RS_SPRITE_COORD_ENABLE);
    561    tmp = get_buf_entry(ctx, VIRGL_OBJ_RS_S3);
    562    emask(line_stipple_pattern, 0, 0xffff);
    563    emask(line_stipple_factor, 16, 0xff);
    564    emask(clip_plane_enable, 24, 0xff);
    565 
    566    rs_state->line_width = uif(get_buf_entry(ctx, VIRGL_OBJ_RS_LINE_WIDTH));
    567    rs_state->offset_units = uif(get_buf_entry(ctx, VIRGL_OBJ_RS_OFFSET_UNITS));
    568    rs_state->offset_scale = uif(get_buf_entry(ctx, VIRGL_OBJ_RS_OFFSET_SCALE));
    569    rs_state->offset_clamp = uif(get_buf_entry(ctx, VIRGL_OBJ_RS_OFFSET_CLAMP));
    570 
    571    tmp = vrend_renderer_object_insert(ctx->grctx, rs_state, sizeof(struct pipe_rasterizer_state), handle,
    572                                       VIRGL_OBJECT_RASTERIZER);
    573    if (tmp == 0) {
    574       FREE(rs_state);
    575       return ENOMEM;
    576    }
    577    return 0;
    578 }
    579 
    580 static int vrend_decode_create_surface(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
    581 {
    582    uint32_t res_handle, format, val0, val1;
    583    int ret;
    584 
    585    if (length != VIRGL_OBJ_SURFACE_SIZE)
    586       return EINVAL;
    587 
    588    res_handle = get_buf_entry(ctx, VIRGL_OBJ_SURFACE_RES_HANDLE);
    589    format = get_buf_entry(ctx, VIRGL_OBJ_SURFACE_FORMAT);
    590    /* decide later if these are texture or buffer */
    591    val0 = get_buf_entry(ctx, VIRGL_OBJ_SURFACE_BUFFER_FIRST_ELEMENT);
    592    val1 = get_buf_entry(ctx, VIRGL_OBJ_SURFACE_BUFFER_LAST_ELEMENT);
    593    ret = vrend_create_surface(ctx->grctx, handle, res_handle, format, val0, val1);
    594    return ret;
    595 }
    596 
    597 static int vrend_decode_create_sampler_view(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
    598 {
    599    uint32_t res_handle, format, val0, val1, swizzle_packed;
    600 
    601    if (length != VIRGL_OBJ_SAMPLER_VIEW_SIZE)
    602       return EINVAL;
    603 
    604    res_handle = get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_VIEW_RES_HANDLE);
    605    format = get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_VIEW_FORMAT);
    606    val0 = get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_VIEW_BUFFER_FIRST_ELEMENT);
    607    val1 = get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_VIEW_BUFFER_LAST_ELEMENT);
    608    swizzle_packed = get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE);
    609    return vrend_create_sampler_view(ctx->grctx, handle, res_handle, format, val0, val1,swizzle_packed);
    610 }
    611 
    612 static int vrend_decode_create_sampler_state(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
    613 {
    614    struct pipe_sampler_state state;
    615    int i;
    616    uint32_t tmp;
    617 
    618    if (length != VIRGL_OBJ_SAMPLER_STATE_SIZE)
    619       return EINVAL;
    620    tmp = get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_STATE_S0);
    621    state.wrap_s = tmp & 0x7;
    622    state.wrap_t = (tmp >> 3) & 0x7;
    623    state.wrap_r = (tmp >> 6) & 0x7;
    624    state.min_img_filter = (tmp >> 9) & 0x3;
    625    state.min_mip_filter = (tmp >> 11) & 0x3;
    626    state.mag_img_filter = (tmp >> 13) & 0x3;
    627    state.compare_mode = (tmp >> 15) & 0x1;
    628    state.compare_func = (tmp >> 16) & 0x7;
    629    state.seamless_cube_map = (tmp >> 19) & 0x1;
    630 
    631    state.lod_bias = uif(get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_STATE_LOD_BIAS));
    632    state.min_lod = uif(get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_STATE_MIN_LOD));
    633    state.max_lod = uif(get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_STATE_MAX_LOD));
    634 
    635    for (i = 0; i < 4; i++)
    636       state.border_color.ui[i] = get_buf_entry(ctx, VIRGL_OBJ_SAMPLER_STATE_BORDER_COLOR(i));
    637    return vrend_create_sampler_state(ctx->grctx, handle, &state);
    638 }
    639 
    640 static int vrend_decode_create_ve(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
    641 {
    642    struct pipe_vertex_element *ve = NULL;
    643    int num_elements;
    644    int i;
    645    int ret;
    646 
    647    if (length < 1)
    648       return EINVAL;
    649 
    650    if ((length - 1) % 4)
    651       return EINVAL;
    652 
    653    num_elements = (length - 1) / 4;
    654 
    655    if (num_elements) {
    656       ve = calloc(num_elements, sizeof(struct pipe_vertex_element));
    657 
    658       if (!ve)
    659          return ENOMEM;
    660 
    661       for (i = 0; i < num_elements; i++) {
    662          ve[i].src_offset = get_buf_entry(ctx, VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_OFFSET(i));
    663          ve[i].instance_divisor = get_buf_entry(ctx, VIRGL_OBJ_VERTEX_ELEMENTS_V0_INSTANCE_DIVISOR(i));
    664          ve[i].vertex_buffer_index = get_buf_entry(ctx, VIRGL_OBJ_VERTEX_ELEMENTS_V0_VERTEX_BUFFER_INDEX(i));
    665 
    666          if (ve[i].vertex_buffer_index >= PIPE_MAX_ATTRIBS) {
    667             FREE(ve);
    668             return EINVAL;
    669          }
    670 
    671          ve[i].src_format = get_buf_entry(ctx, VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_FORMAT(i));
    672       }
    673    }
    674 
    675    ret = vrend_create_vertex_elements_state(ctx->grctx, handle, num_elements, ve);
    676 
    677    FREE(ve);
    678    return ret;
    679 }
    680 
    681 static int vrend_decode_create_query(struct vrend_decode_ctx *ctx, uint32_t handle, uint16_t length)
    682 {
    683    uint32_t query_type;
    684    uint32_t query_index;
    685    uint32_t res_handle;
    686    uint32_t offset;
    687    uint32_t tmp;
    688 
    689    if (length != VIRGL_OBJ_QUERY_SIZE)
    690       return EINVAL;
    691 
    692    tmp = get_buf_entry(ctx, VIRGL_OBJ_QUERY_TYPE_INDEX);
    693    query_type = VIRGL_OBJ_QUERY_TYPE(tmp);
    694    query_index = (tmp >> 16) & 0xffff;
    695 
    696    offset = get_buf_entry(ctx, VIRGL_OBJ_QUERY_OFFSET);
    697    res_handle = get_buf_entry(ctx, VIRGL_OBJ_QUERY_RES_HANDLE);
    698 
    699    return vrend_create_query(ctx->grctx, handle, query_type, query_index, res_handle, offset);
    700 }
    701 
    702 static int vrend_decode_create_object(struct vrend_decode_ctx *ctx, int length)
    703 {
    704    if (length < 1)
    705       return EINVAL;
    706 
    707    uint32_t header = get_buf_entry(ctx, VIRGL_OBJ_CREATE_HEADER);
    708    uint32_t handle = get_buf_entry(ctx, VIRGL_OBJ_CREATE_HANDLE);
    709    uint8_t obj_type = (header >> 8) & 0xff;
    710    int ret = 0;
    711 
    712    if (handle == 0)
    713       return EINVAL;
    714 
    715    switch (obj_type){
    716    case VIRGL_OBJECT_BLEND:
    717       ret = vrend_decode_create_blend(ctx, handle, length);
    718       break;
    719    case VIRGL_OBJECT_DSA:
    720       ret = vrend_decode_create_dsa(ctx, handle, length);
    721       break;
    722    case VIRGL_OBJECT_RASTERIZER:
    723       ret = vrend_decode_create_rasterizer(ctx, handle, length);
    724       break;
    725    case VIRGL_OBJECT_SHADER:
    726       ret = vrend_decode_create_shader(ctx, handle, length);
    727       break;
    728    case VIRGL_OBJECT_VERTEX_ELEMENTS:
    729       ret = vrend_decode_create_ve(ctx, handle, length);
    730       break;
    731    case VIRGL_OBJECT_SURFACE:
    732       ret = vrend_decode_create_surface(ctx, handle, length);
    733       break;
    734    case VIRGL_OBJECT_SAMPLER_VIEW:
    735       ret = vrend_decode_create_sampler_view(ctx, handle, length);
    736       break;
    737    case VIRGL_OBJECT_SAMPLER_STATE:
    738       ret = vrend_decode_create_sampler_state(ctx, handle, length);
    739       break;
    740    case VIRGL_OBJECT_QUERY:
    741       ret = vrend_decode_create_query(ctx, handle, length);
    742       break;
    743    case VIRGL_OBJECT_STREAMOUT_TARGET:
    744       ret = vrend_decode_create_stream_output_target(ctx, handle, length);
    745       break;
    746    default:
    747       return EINVAL;
    748    }
    749 
    750    return ret;
    751 }
    752 
    753 static int vrend_decode_bind_object(struct vrend_decode_ctx *ctx, uint16_t length)
    754 {
    755    if (length != 1)
    756       return EINVAL;
    757 
    758    uint32_t header = get_buf_entry(ctx, VIRGL_OBJ_BIND_HEADER);
    759    uint32_t handle = get_buf_entry(ctx, VIRGL_OBJ_BIND_HANDLE);
    760    uint8_t obj_type = (header >> 8) & 0xff;
    761 
    762    switch (obj_type) {
    763    case VIRGL_OBJECT_BLEND:
    764       vrend_object_bind_blend(ctx->grctx, handle);
    765       break;
    766    case VIRGL_OBJECT_DSA:
    767       vrend_object_bind_dsa(ctx->grctx, handle);
    768       break;
    769    case VIRGL_OBJECT_RASTERIZER:
    770       vrend_object_bind_rasterizer(ctx->grctx, handle);
    771       break;
    772    case VIRGL_OBJECT_VERTEX_ELEMENTS:
    773       vrend_bind_vertex_elements_state(ctx->grctx, handle);
    774       break;
    775    default:
    776       return EINVAL;
    777    }
    778 
    779    return 0;
    780 }
    781 
    782 static int vrend_decode_destroy_object(struct vrend_decode_ctx *ctx, int length)
    783 {
    784    if (length != 1)
    785       return EINVAL;
    786 
    787    uint32_t handle = get_buf_entry(ctx, VIRGL_OBJ_DESTROY_HANDLE);
    788 
    789    vrend_renderer_object_destroy(ctx->grctx, handle);
    790    return 0;
    791 }
    792 
    793 static int vrend_decode_set_stencil_ref(struct vrend_decode_ctx *ctx, int length)
    794 {
    795    if (length != VIRGL_SET_STENCIL_REF_SIZE)
    796       return EINVAL;
    797 
    798    struct pipe_stencil_ref ref;
    799    uint32_t val = get_buf_entry(ctx, VIRGL_SET_STENCIL_REF);
    800 
    801    ref.ref_value[0] = val & 0xff;
    802    ref.ref_value[1] = (val >> 8) & 0xff;
    803    vrend_set_stencil_ref(ctx->grctx, &ref);
    804    return 0;
    805 }
    806 
    807 static int vrend_decode_set_blend_color(struct vrend_decode_ctx *ctx, int length)
    808 {
    809    struct pipe_blend_color color;
    810    int i;
    811 
    812    if (length != VIRGL_SET_BLEND_COLOR_SIZE)
    813       return EINVAL;
    814 
    815    for (i = 0; i < 4; i++)
    816       color.color[i] = uif(get_buf_entry(ctx, VIRGL_SET_BLEND_COLOR(i)));
    817 
    818    vrend_set_blend_color(ctx->grctx, &color);
    819    return 0;
    820 }
    821 
    822 static int vrend_decode_set_scissor_state(struct vrend_decode_ctx *ctx, int length)
    823 {
    824    struct pipe_scissor_state ss[PIPE_MAX_VIEWPORTS];
    825    uint32_t temp;
    826    int32_t num_scissor;
    827    uint32_t start_slot;
    828    int s;
    829    if (length < 1)
    830       return EINVAL;
    831 
    832    if ((length - 1) % 2)
    833       return EINVAL;
    834 
    835    num_scissor = (length - 1) / 2;
    836    if (num_scissor > PIPE_MAX_VIEWPORTS)
    837       return EINVAL;
    838 
    839    start_slot = get_buf_entry(ctx, VIRGL_SET_SCISSOR_START_SLOT);
    840 
    841    for (s = 0; s < num_scissor; s++) {
    842       temp = get_buf_entry(ctx, VIRGL_SET_SCISSOR_MINX_MINY(s));
    843       ss[s].minx = temp & 0xffff;
    844       ss[s].miny = (temp >> 16) & 0xffff;
    845 
    846       temp = get_buf_entry(ctx, VIRGL_SET_SCISSOR_MAXX_MAXY(s));
    847       ss[s].maxx = temp & 0xffff;
    848       ss[s].maxy = (temp >> 16) & 0xffff;
    849    }
    850 
    851    vrend_set_scissor_state(ctx->grctx, start_slot, num_scissor, ss);
    852    return 0;
    853 }
    854 
    855 static int vrend_decode_set_polygon_stipple(struct vrend_decode_ctx *ctx, int length)
    856 {
    857    struct pipe_poly_stipple ps;
    858    int i;
    859 
    860    if (length != VIRGL_POLYGON_STIPPLE_SIZE)
    861       return EINVAL;
    862 
    863    for (i = 0; i < 32; i++)
    864       ps.stipple[i] = get_buf_entry(ctx, VIRGL_POLYGON_STIPPLE_P0 + i);
    865 
    866    vrend_set_polygon_stipple(ctx->grctx, &ps);
    867    return 0;
    868 }
    869 
    870 static int vrend_decode_set_clip_state(struct vrend_decode_ctx *ctx, int length)
    871 {
    872    struct pipe_clip_state clip;
    873    int i, j;
    874 
    875    if (length != VIRGL_SET_CLIP_STATE_SIZE)
    876       return EINVAL;
    877 
    878    for (i = 0; i < 8; i++)
    879       for (j = 0; j < 4; j++)
    880          clip.ucp[i][j] = uif(get_buf_entry(ctx, VIRGL_SET_CLIP_STATE_C0 + (i * 4) + j));
    881    vrend_set_clip_state(ctx->grctx, &clip);
    882    return 0;
    883 }
    884 
    885 static int vrend_decode_set_sample_mask(struct vrend_decode_ctx *ctx, int length)
    886 {
    887    unsigned mask;
    888 
    889    if (length != VIRGL_SET_SAMPLE_MASK_SIZE)
    890       return EINVAL;
    891    mask = get_buf_entry(ctx, VIRGL_SET_SAMPLE_MASK_MASK);
    892    vrend_set_sample_mask(ctx->grctx, mask);
    893    return 0;
    894 }
    895 
    896 static int vrend_decode_set_min_samples(struct vrend_decode_ctx *ctx, int length)
    897 {
    898    unsigned min_samples;
    899 
    900    if (length != VIRGL_SET_MIN_SAMPLES_SIZE)
    901       return EINVAL;
    902    min_samples = get_buf_entry(ctx, VIRGL_SET_MIN_SAMPLES_MASK);
    903    vrend_set_min_samples(ctx->grctx, min_samples);
    904    return 0;
    905 }
    906 
    907 static int vrend_decode_resource_copy_region(struct vrend_decode_ctx *ctx, int length)
    908 {
    909    struct pipe_box box;
    910    uint32_t dst_handle, src_handle;
    911    uint32_t dst_level, dstx, dsty, dstz;
    912    uint32_t src_level;
    913 
    914    if (length != VIRGL_CMD_RESOURCE_COPY_REGION_SIZE)
    915       return EINVAL;
    916 
    917    dst_handle = get_buf_entry(ctx, VIRGL_CMD_RCR_DST_RES_HANDLE);
    918    dst_level = get_buf_entry(ctx, VIRGL_CMD_RCR_DST_LEVEL);
    919    dstx = get_buf_entry(ctx, VIRGL_CMD_RCR_DST_X);
    920    dsty = get_buf_entry(ctx, VIRGL_CMD_RCR_DST_Y);
    921    dstz = get_buf_entry(ctx, VIRGL_CMD_RCR_DST_Z);
    922    src_handle = get_buf_entry(ctx, VIRGL_CMD_RCR_SRC_RES_HANDLE);
    923    src_level = get_buf_entry(ctx, VIRGL_CMD_RCR_SRC_LEVEL);
    924    box.x = get_buf_entry(ctx, VIRGL_CMD_RCR_SRC_X);
    925    box.y = get_buf_entry(ctx, VIRGL_CMD_RCR_SRC_Y);
    926    box.z = get_buf_entry(ctx, VIRGL_CMD_RCR_SRC_Z);
    927    box.width = get_buf_entry(ctx, VIRGL_CMD_RCR_SRC_W);
    928    box.height = get_buf_entry(ctx, VIRGL_CMD_RCR_SRC_H);
    929    box.depth = get_buf_entry(ctx, VIRGL_CMD_RCR_SRC_D);
    930 
    931    vrend_renderer_resource_copy_region(ctx->grctx, dst_handle,
    932                                        dst_level, dstx, dsty, dstz,
    933                                        src_handle, src_level,
    934                                        &box);
    935    return 0;
    936 }
    937 
    938 
    939 static int vrend_decode_blit(struct vrend_decode_ctx *ctx, int length)
    940 {
    941    struct pipe_blit_info info;
    942    uint32_t dst_handle, src_handle, temp;
    943 
    944    if (length != VIRGL_CMD_BLIT_SIZE)
    945       return EINVAL;
    946    temp = get_buf_entry(ctx, VIRGL_CMD_BLIT_S0);
    947    info.mask = temp & 0xff;
    948    info.filter = (temp >> 8) & 0x3;
    949    info.scissor_enable = (temp >> 10) & 0x1;
    950    info.render_condition_enable = (temp >> 11) & 0x1;
    951    info.alpha_blend = (temp >> 12) & 0x1;
    952    temp = get_buf_entry(ctx, VIRGL_CMD_BLIT_SCISSOR_MINX_MINY);
    953    info.scissor.minx = temp & 0xffff;
    954    info.scissor.miny = (temp >> 16) & 0xffff;
    955    temp = get_buf_entry(ctx, VIRGL_CMD_BLIT_SCISSOR_MAXX_MAXY);
    956    info.scissor.maxx = temp & 0xffff;
    957    info.scissor.maxy = (temp >> 16) & 0xffff;
    958    dst_handle = get_buf_entry(ctx, VIRGL_CMD_BLIT_DST_RES_HANDLE);
    959    info.dst.level = get_buf_entry(ctx, VIRGL_CMD_BLIT_DST_LEVEL);
    960    info.dst.format = get_buf_entry(ctx, VIRGL_CMD_BLIT_DST_FORMAT);
    961    info.dst.box.x = get_buf_entry(ctx, VIRGL_CMD_BLIT_DST_X);
    962    info.dst.box.y = get_buf_entry(ctx, VIRGL_CMD_BLIT_DST_Y);
    963    info.dst.box.z = get_buf_entry(ctx, VIRGL_CMD_BLIT_DST_Z);
    964    info.dst.box.width = get_buf_entry(ctx, VIRGL_CMD_BLIT_DST_W);
    965    info.dst.box.height = get_buf_entry(ctx, VIRGL_CMD_BLIT_DST_H);
    966    info.dst.box.depth = get_buf_entry(ctx, VIRGL_CMD_BLIT_DST_D);
    967 
    968    src_handle = get_buf_entry(ctx, VIRGL_CMD_BLIT_SRC_RES_HANDLE);
    969    info.src.level = get_buf_entry(ctx, VIRGL_CMD_BLIT_SRC_LEVEL);
    970    info.src.format = get_buf_entry(ctx, VIRGL_CMD_BLIT_SRC_FORMAT);
    971    info.src.box.x = get_buf_entry(ctx, VIRGL_CMD_BLIT_SRC_X);
    972    info.src.box.y = get_buf_entry(ctx, VIRGL_CMD_BLIT_SRC_Y);
    973    info.src.box.z = get_buf_entry(ctx, VIRGL_CMD_BLIT_SRC_Z);
    974    info.src.box.width = get_buf_entry(ctx, VIRGL_CMD_BLIT_SRC_W);
    975    info.src.box.height = get_buf_entry(ctx, VIRGL_CMD_BLIT_SRC_H);
    976    info.src.box.depth = get_buf_entry(ctx, VIRGL_CMD_BLIT_SRC_D);
    977 
    978    vrend_renderer_blit(ctx->grctx, dst_handle, src_handle, &info);
    979    return 0;
    980 }
    981 
    982 static int vrend_decode_bind_sampler_states(struct vrend_decode_ctx *ctx, int length)
    983 {
    984    if (length < 2)
    985       return EINVAL;
    986 
    987    uint32_t shader_type = get_buf_entry(ctx, VIRGL_BIND_SAMPLER_STATES_SHADER_TYPE);
    988    uint32_t start_slot = get_buf_entry(ctx, VIRGL_BIND_SAMPLER_STATES_START_SLOT);
    989    uint32_t num_states = length - 2;
    990 
    991    if (shader_type >= PIPE_SHADER_TYPES)
    992       return EINVAL;
    993 
    994    vrend_bind_sampler_states(ctx->grctx, shader_type, start_slot, num_states,
    995                              get_buf_ptr(ctx, VIRGL_BIND_SAMPLER_STATES_S0_HANDLE));
    996    return 0;
    997 }
    998 
    999 static int vrend_decode_begin_query(struct vrend_decode_ctx *ctx, int length)
   1000 {
   1001    if (length != 1)
   1002       return EINVAL;
   1003 
   1004    uint32_t handle = get_buf_entry(ctx, VIRGL_QUERY_BEGIN_HANDLE);
   1005 
   1006    return vrend_begin_query(ctx->grctx, handle);
   1007 }
   1008 
   1009 static int vrend_decode_end_query(struct vrend_decode_ctx *ctx, int length)
   1010 {
   1011    if (length != 1)
   1012       return EINVAL;
   1013 
   1014    uint32_t handle = get_buf_entry(ctx, VIRGL_QUERY_END_HANDLE);
   1015 
   1016    return vrend_end_query(ctx->grctx, handle);
   1017 }
   1018 
   1019 static int vrend_decode_get_query_result(struct vrend_decode_ctx *ctx, int length)
   1020 {
   1021    if (length != 2)
   1022       return EINVAL;
   1023 
   1024    uint32_t handle = get_buf_entry(ctx, VIRGL_QUERY_RESULT_HANDLE);
   1025    uint32_t wait = get_buf_entry(ctx, VIRGL_QUERY_RESULT_WAIT);
   1026 
   1027    vrend_get_query_result(ctx->grctx, handle, wait);
   1028    return 0;
   1029 }
   1030 
   1031 static int vrend_decode_set_render_condition(struct vrend_decode_ctx *ctx, int length)
   1032 {
   1033    if (length != VIRGL_RENDER_CONDITION_SIZE)
   1034       return EINVAL;
   1035 
   1036    uint32_t handle = get_buf_entry(ctx, VIRGL_RENDER_CONDITION_HANDLE);
   1037    bool condition = get_buf_entry(ctx, VIRGL_RENDER_CONDITION_CONDITION) & 1;
   1038    uint mode = get_buf_entry(ctx, VIRGL_RENDER_CONDITION_MODE);
   1039 
   1040    vrend_render_condition(ctx->grctx, handle, condition, mode);
   1041    return 0;
   1042 }
   1043 
   1044 static int vrend_decode_set_sub_ctx(struct vrend_decode_ctx *ctx, int length)
   1045 {
   1046    if (length != 1)
   1047       return EINVAL;
   1048 
   1049    uint32_t ctx_sub_id = get_buf_entry(ctx, 1);
   1050 
   1051    vrend_renderer_set_sub_ctx(ctx->grctx, ctx_sub_id);
   1052    return 0;
   1053 }
   1054 
   1055 static int vrend_decode_create_sub_ctx(struct vrend_decode_ctx *ctx, int length)
   1056 {
   1057    if (length != 1)
   1058       return EINVAL;
   1059 
   1060    uint32_t ctx_sub_id = get_buf_entry(ctx, 1);
   1061 
   1062    vrend_renderer_create_sub_ctx(ctx->grctx, ctx_sub_id);
   1063    return 0;
   1064 }
   1065 
   1066 static int vrend_decode_destroy_sub_ctx(struct vrend_decode_ctx *ctx, int length)
   1067 {
   1068    if (length != 1)
   1069       return EINVAL;
   1070 
   1071    uint32_t ctx_sub_id = get_buf_entry(ctx, 1);
   1072 
   1073    vrend_renderer_destroy_sub_ctx(ctx->grctx, ctx_sub_id);
   1074    return 0;
   1075 }
   1076 
   1077 static int vrend_decode_bind_shader(struct vrend_decode_ctx *ctx, int length)
   1078 {
   1079    uint32_t handle, type;
   1080    if (length != VIRGL_BIND_SHADER_SIZE)
   1081       return EINVAL;
   1082 
   1083    handle = get_buf_entry(ctx, VIRGL_BIND_SHADER_HANDLE);
   1084    type = get_buf_entry(ctx, VIRGL_BIND_SHADER_TYPE);
   1085 
   1086    vrend_bind_shader(ctx->grctx, handle, type);
   1087    return 0;
   1088 }
   1089 
   1090 static int vrend_decode_set_tess_state(struct vrend_decode_ctx *ctx,
   1091 				       int length)
   1092 {
   1093    float tess_factors[6];
   1094    int i;
   1095 
   1096    if (length != VIRGL_TESS_STATE_SIZE)
   1097       return EINVAL;
   1098 
   1099    for (i = 0; i < 6; i++) {
   1100       tess_factors[i] = uif(get_buf_entry(ctx, i + 1));
   1101    }
   1102    vrend_set_tess_state(ctx->grctx, tess_factors);
   1103    return 0;
   1104 }
   1105 
   1106 static int vrend_decode_set_shader_buffers(struct vrend_decode_ctx *ctx, uint16_t length)
   1107 {
   1108    int num_ssbo;
   1109    uint32_t shader_type, start_slot;
   1110 
   1111    if (length < 2)
   1112       return EINVAL;
   1113 
   1114    num_ssbo = (length - 2) / VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE;
   1115    shader_type = get_buf_entry(ctx, VIRGL_SET_SHADER_BUFFER_SHADER_TYPE);
   1116    start_slot = get_buf_entry(ctx, VIRGL_SET_SHADER_BUFFER_START_SLOT);
   1117    if (shader_type >= PIPE_SHADER_TYPES)
   1118       return EINVAL;
   1119 
   1120    if (num_ssbo < 1)
   1121       return 0;
   1122 
   1123    if (start_slot + num_ssbo > PIPE_MAX_SHADER_BUFFERS)
   1124       return EINVAL;
   1125 
   1126    for (int i = 0; i < num_ssbo; i++) {
   1127       uint32_t offset = get_buf_entry(ctx, VIRGL_SET_SHADER_BUFFER_OFFSET(i));
   1128       uint32_t buf_len = get_buf_entry(ctx, VIRGL_SET_SHADER_BUFFER_LENGTH(i));
   1129       uint32_t handle = get_buf_entry(ctx, VIRGL_SET_SHADER_BUFFER_RES_HANDLE(i));
   1130       vrend_set_single_ssbo(ctx->grctx, shader_type, start_slot + i, offset, buf_len,
   1131                             handle);
   1132    }
   1133    return 0;
   1134 }
   1135 
   1136 static int vrend_decode_set_shader_images(struct vrend_decode_ctx *ctx, uint16_t length)
   1137 {
   1138    int num_images;
   1139    uint32_t shader_type, start_slot;
   1140    if (length < 2)
   1141       return EINVAL;
   1142 
   1143    num_images = (length - 2) / VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE;
   1144    shader_type = get_buf_entry(ctx, VIRGL_SET_SHADER_IMAGE_SHADER_TYPE);
   1145    start_slot = get_buf_entry(ctx, VIRGL_SET_SHADER_IMAGE_START_SLOT);
   1146    if (shader_type >= PIPE_SHADER_TYPES)
   1147       return EINVAL;
   1148 
   1149    if (num_images < 1) {
   1150       return 0;
   1151    }
   1152    if (start_slot + num_images > PIPE_MAX_SHADER_IMAGES)
   1153       return EINVAL;
   1154 
   1155    for (int i = 0; i < num_images; i++) {
   1156       uint32_t format = get_buf_entry(ctx, VIRGL_SET_SHADER_IMAGE_FORMAT(i));
   1157       uint32_t access = get_buf_entry(ctx, VIRGL_SET_SHADER_IMAGE_ACCESS(i));
   1158       uint32_t layer_offset = get_buf_entry(ctx, VIRGL_SET_SHADER_IMAGE_LAYER_OFFSET(i));
   1159       uint32_t level_size = get_buf_entry(ctx, VIRGL_SET_SHADER_IMAGE_LEVEL_SIZE(i));
   1160       uint32_t handle = get_buf_entry(ctx, VIRGL_SET_SHADER_IMAGE_RES_HANDLE(i));
   1161       vrend_set_single_image_view(ctx->grctx, shader_type, start_slot + i, format, access,
   1162                                   layer_offset, level_size, handle);
   1163    }
   1164    return 0;
   1165 }
   1166 
   1167 static int vrend_decode_memory_barrier(struct vrend_decode_ctx *ctx, uint16_t length)
   1168 {
   1169    if (length != VIRGL_MEMORY_BARRIER_SIZE)
   1170       return EINVAL;
   1171 
   1172    unsigned flags = get_buf_entry(ctx, VIRGL_MEMORY_BARRIER_FLAGS);
   1173    vrend_memory_barrier(ctx->grctx, flags);
   1174    return 0;
   1175 }
   1176 
   1177 static int vrend_decode_launch_grid(struct vrend_decode_ctx *ctx, uint16_t length)
   1178 {
   1179    uint32_t block[3], grid[3];
   1180    uint32_t indirect_handle, indirect_offset;
   1181    if (length != VIRGL_LAUNCH_GRID_SIZE)
   1182       return EINVAL;
   1183 
   1184    block[0] = get_buf_entry(ctx, VIRGL_LAUNCH_BLOCK_X);
   1185    block[1] = get_buf_entry(ctx, VIRGL_LAUNCH_BLOCK_Y);
   1186    block[2] = get_buf_entry(ctx, VIRGL_LAUNCH_BLOCK_Z);
   1187    grid[0] = get_buf_entry(ctx, VIRGL_LAUNCH_GRID_X);
   1188    grid[1] = get_buf_entry(ctx, VIRGL_LAUNCH_GRID_Y);
   1189    grid[2] = get_buf_entry(ctx, VIRGL_LAUNCH_GRID_Z);
   1190    indirect_handle = get_buf_entry(ctx, VIRGL_LAUNCH_INDIRECT_HANDLE);
   1191    indirect_offset = get_buf_entry(ctx, VIRGL_LAUNCH_INDIRECT_OFFSET);
   1192    vrend_launch_grid(ctx->grctx, block, grid, indirect_handle, indirect_offset);
   1193    return 0;
   1194 }
   1195 
   1196 static int vrend_decode_set_streamout_targets(struct vrend_decode_ctx *ctx,
   1197                                               uint16_t length)
   1198 {
   1199    uint32_t handles[16];
   1200    uint32_t num_handles = length - 1;
   1201    uint32_t append_bitmask;
   1202    uint i;
   1203 
   1204    if (length < 1)
   1205       return EINVAL;
   1206    if (num_handles > ARRAY_SIZE(handles))
   1207       return EINVAL;
   1208 
   1209    append_bitmask = get_buf_entry(ctx, VIRGL_SET_STREAMOUT_TARGETS_APPEND_BITMASK);
   1210    for (i = 0; i < num_handles; i++)
   1211       handles[i] = get_buf_entry(ctx, VIRGL_SET_STREAMOUT_TARGETS_H0 + i);
   1212    vrend_set_streamout_targets(ctx->grctx, append_bitmask, num_handles, handles);
   1213    return 0;
   1214 }
   1215 
   1216 static int vrend_decode_texture_barrier(struct vrend_decode_ctx *ctx, uint16_t length)
   1217 {
   1218    if (length != VIRGL_TEXTURE_BARRIER_SIZE)
   1219       return EINVAL;
   1220 
   1221    unsigned flags = get_buf_entry(ctx, VIRGL_TEXTURE_BARRIER_FLAGS);
   1222    vrend_texture_barrier(ctx->grctx, flags);
   1223    return 0;
   1224 }
   1225 
   1226 void vrend_renderer_context_create_internal(uint32_t handle, uint32_t nlen,
   1227                                             const char *debug_name)
   1228 {
   1229    struct vrend_decode_ctx *dctx;
   1230 
   1231    if (handle >= VREND_MAX_CTX)
   1232       return;
   1233 
   1234    dctx = dec_ctx[handle];
   1235    if (dctx)
   1236       return;
   1237 
   1238    dctx = malloc(sizeof(struct vrend_decode_ctx));
   1239    if (!dctx)
   1240       return;
   1241 
   1242    dctx->grctx = vrend_create_context(handle, nlen, debug_name);
   1243    if (!dctx->grctx) {
   1244       free(dctx);
   1245       return;
   1246    }
   1247 
   1248    dctx->ds = &dctx->ids;
   1249 
   1250    dec_ctx[handle] = dctx;
   1251 }
   1252 
   1253 int vrend_renderer_context_create(uint32_t handle, uint32_t nlen, const char *debug_name)
   1254 {
   1255    if (handle >= VREND_MAX_CTX)
   1256       return EINVAL;
   1257 
   1258    /* context 0 is always available with no guarantees */
   1259    if (handle == 0)
   1260       return EINVAL;
   1261 
   1262    vrend_renderer_context_create_internal(handle, nlen, debug_name);
   1263    return 0;
   1264 }
   1265 
   1266 void vrend_renderer_context_destroy(uint32_t handle)
   1267 {
   1268    struct vrend_decode_ctx *ctx;
   1269    bool ret;
   1270 
   1271    if (handle >= VREND_MAX_CTX)
   1272       return;
   1273 
   1274    /* never destroy context 0 here, it will be destroyed in vrend_decode_reset()*/
   1275    if (handle == 0) {
   1276       return;
   1277    }
   1278 
   1279    ctx = dec_ctx[handle];
   1280    if (!ctx)
   1281       return;
   1282    dec_ctx[handle] = NULL;
   1283    ret = vrend_destroy_context(ctx->grctx);
   1284    free(ctx);
   1285    /* switch to ctx 0 */
   1286    if (ret && handle != 0)
   1287       vrend_hw_switch_context(dec_ctx[0]->grctx, true);
   1288 }
   1289 
   1290 struct vrend_context *vrend_lookup_renderer_ctx(uint32_t ctx_id)
   1291 {
   1292    if (ctx_id >= VREND_MAX_CTX)
   1293       return NULL;
   1294 
   1295    if (dec_ctx[ctx_id] == NULL)
   1296       return NULL;
   1297 
   1298    return dec_ctx[ctx_id]->grctx;
   1299 }
   1300 
   1301 int vrend_decode_block(uint32_t ctx_id, uint32_t *block, int ndw)
   1302 {
   1303    struct vrend_decode_ctx *gdctx;
   1304    bool bret;
   1305    int ret;
   1306    if (ctx_id >= VREND_MAX_CTX)
   1307       return EINVAL;
   1308 
   1309    if (dec_ctx[ctx_id] == NULL)
   1310       return EINVAL;
   1311 
   1312    gdctx = dec_ctx[ctx_id];
   1313 
   1314    bret = vrend_hw_switch_context(gdctx->grctx, true);
   1315    if (bret == false)
   1316       return EINVAL;
   1317 
   1318    gdctx->ds->buf = block;
   1319    gdctx->ds->buf_total = ndw;
   1320    gdctx->ds->buf_offset = 0;
   1321 
   1322    while (gdctx->ds->buf_offset < gdctx->ds->buf_total) {
   1323       uint32_t header = gdctx->ds->buf[gdctx->ds->buf_offset];
   1324       uint32_t len = header >> 16;
   1325 
   1326       ret = 0;
   1327       /* check if the guest is doing something bad */
   1328       if (gdctx->ds->buf_offset + len + 1 > gdctx->ds->buf_total) {
   1329          vrend_report_buffer_error(gdctx->grctx, 0);
   1330          break;
   1331       }
   1332 //      fprintf(stderr,"[%d] cmd is %d (obj %d) len %d\n", gdctx->ds->buf_offset, header & 0xff, (header >> 8 & 0xff), (len));
   1333 
   1334       switch (header & 0xff) {
   1335       case VIRGL_CCMD_CREATE_OBJECT:
   1336          ret = vrend_decode_create_object(gdctx, len);
   1337          break;
   1338       case VIRGL_CCMD_BIND_OBJECT:
   1339          ret = vrend_decode_bind_object(gdctx, len);
   1340          break;
   1341       case VIRGL_CCMD_DESTROY_OBJECT:
   1342          ret = vrend_decode_destroy_object(gdctx, len);
   1343          break;
   1344       case VIRGL_CCMD_CLEAR:
   1345          ret = vrend_decode_clear(gdctx, len);
   1346          break;
   1347       case VIRGL_CCMD_DRAW_VBO:
   1348          ret = vrend_decode_draw_vbo(gdctx, len);
   1349          break;
   1350       case VIRGL_CCMD_SET_FRAMEBUFFER_STATE:
   1351          ret = vrend_decode_set_framebuffer_state(gdctx, len);
   1352          break;
   1353       case VIRGL_CCMD_SET_VERTEX_BUFFERS:
   1354          ret = vrend_decode_set_vertex_buffers(gdctx, len);
   1355          break;
   1356       case VIRGL_CCMD_RESOURCE_INLINE_WRITE:
   1357          ret = vrend_decode_resource_inline_write(gdctx, len);
   1358          break;
   1359       case VIRGL_CCMD_SET_VIEWPORT_STATE:
   1360          ret = vrend_decode_set_viewport_state(gdctx, len);
   1361          break;
   1362       case VIRGL_CCMD_SET_SAMPLER_VIEWS:
   1363          ret = vrend_decode_set_sampler_views(gdctx, len);
   1364          break;
   1365       case VIRGL_CCMD_SET_INDEX_BUFFER:
   1366          ret = vrend_decode_set_index_buffer(gdctx, len);
   1367          break;
   1368       case VIRGL_CCMD_SET_CONSTANT_BUFFER:
   1369          ret = vrend_decode_set_constant_buffer(gdctx, len);
   1370          break;
   1371       case VIRGL_CCMD_SET_STENCIL_REF:
   1372          ret = vrend_decode_set_stencil_ref(gdctx, len);
   1373          break;
   1374       case VIRGL_CCMD_SET_BLEND_COLOR:
   1375          ret = vrend_decode_set_blend_color(gdctx, len);
   1376          break;
   1377       case VIRGL_CCMD_SET_SCISSOR_STATE:
   1378          ret = vrend_decode_set_scissor_state(gdctx, len);
   1379          break;
   1380       case VIRGL_CCMD_BLIT:
   1381          ret = vrend_decode_blit(gdctx, len);
   1382          break;
   1383       case VIRGL_CCMD_RESOURCE_COPY_REGION:
   1384          ret = vrend_decode_resource_copy_region(gdctx, len);
   1385          break;
   1386       case VIRGL_CCMD_BIND_SAMPLER_STATES:
   1387          ret = vrend_decode_bind_sampler_states(gdctx, len);
   1388          break;
   1389       case VIRGL_CCMD_BEGIN_QUERY:
   1390          ret = vrend_decode_begin_query(gdctx, len);
   1391          break;
   1392       case VIRGL_CCMD_END_QUERY:
   1393          ret = vrend_decode_end_query(gdctx, len);
   1394          break;
   1395       case VIRGL_CCMD_GET_QUERY_RESULT:
   1396          ret = vrend_decode_get_query_result(gdctx, len);
   1397          break;
   1398       case VIRGL_CCMD_SET_POLYGON_STIPPLE:
   1399          ret = vrend_decode_set_polygon_stipple(gdctx, len);
   1400          break;
   1401       case VIRGL_CCMD_SET_CLIP_STATE:
   1402          ret = vrend_decode_set_clip_state(gdctx, len);
   1403          break;
   1404       case VIRGL_CCMD_SET_SAMPLE_MASK:
   1405          ret = vrend_decode_set_sample_mask(gdctx, len);
   1406          break;
   1407       case VIRGL_CCMD_SET_MIN_SAMPLES:
   1408          ret = vrend_decode_set_min_samples(gdctx, len);
   1409          break;
   1410       case VIRGL_CCMD_SET_STREAMOUT_TARGETS:
   1411          ret = vrend_decode_set_streamout_targets(gdctx, len);
   1412          break;
   1413       case VIRGL_CCMD_SET_RENDER_CONDITION:
   1414          ret = vrend_decode_set_render_condition(gdctx, len);
   1415          break;
   1416       case VIRGL_CCMD_SET_UNIFORM_BUFFER:
   1417          ret = vrend_decode_set_uniform_buffer(gdctx, len);
   1418          break;
   1419       case VIRGL_CCMD_SET_SUB_CTX:
   1420          ret = vrend_decode_set_sub_ctx(gdctx, len);
   1421          break;
   1422       case VIRGL_CCMD_CREATE_SUB_CTX:
   1423          ret = vrend_decode_create_sub_ctx(gdctx, len);
   1424          break;
   1425       case VIRGL_CCMD_DESTROY_SUB_CTX:
   1426          ret = vrend_decode_destroy_sub_ctx(gdctx, len);
   1427          break;
   1428       case VIRGL_CCMD_BIND_SHADER:
   1429          ret = vrend_decode_bind_shader(gdctx, len);
   1430          break;
   1431       case VIRGL_CCMD_SET_TESS_STATE:
   1432          ret = vrend_decode_set_tess_state(gdctx, len);
   1433          break;
   1434       case VIRGL_CCMD_SET_SHADER_BUFFERS:
   1435          ret = vrend_decode_set_shader_buffers(gdctx, len);
   1436          break;
   1437       case VIRGL_CCMD_SET_SHADER_IMAGES:
   1438          ret = vrend_decode_set_shader_images(gdctx, len);
   1439          break;
   1440       case VIRGL_CCMD_MEMORY_BARRIER:
   1441          ret = vrend_decode_memory_barrier(gdctx, len);
   1442          break;
   1443       case VIRGL_CCMD_LAUNCH_GRID:
   1444          ret = vrend_decode_launch_grid(gdctx, len);
   1445          break;
   1446       case VIRGL_CCMD_SET_FRAMEBUFFER_STATE_NO_ATTACH:
   1447          ret = vrend_decode_set_framebuffer_state_no_attach(gdctx, len);
   1448          break;
   1449       case VIRGL_CCMD_TEXTURE_BARRIER:
   1450          ret = vrend_decode_texture_barrier(gdctx, len);
   1451          break;
   1452       default:
   1453          ret = EINVAL;
   1454       }
   1455 
   1456       if (ret == EINVAL) {
   1457          vrend_report_buffer_error(gdctx->grctx, header);
   1458          goto out;
   1459       }
   1460       if (ret == ENOMEM)
   1461          goto out;
   1462       gdctx->ds->buf_offset += (len) + 1;
   1463    }
   1464    return 0;
   1465  out:
   1466    return ret;
   1467 }
   1468 
   1469 void vrend_decode_reset(bool ctx_0_only)
   1470 {
   1471    int i;
   1472 
   1473    vrend_hw_switch_context(dec_ctx[0]->grctx, true);
   1474 
   1475    if (ctx_0_only == false) {
   1476       for (i = 1; i < VREND_MAX_CTX; i++) {
   1477          if (!dec_ctx[i])
   1478             continue;
   1479 
   1480          if (!dec_ctx[i]->grctx)
   1481             continue;
   1482 
   1483          vrend_destroy_context(dec_ctx[i]->grctx);
   1484          free(dec_ctx[i]);
   1485          dec_ctx[i] = NULL;
   1486       }
   1487    } else {
   1488       vrend_destroy_context(dec_ctx[0]->grctx);
   1489       free(dec_ctx[0]);
   1490       dec_ctx[0] = NULL;
   1491    }
   1492 }
   1493