• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_buf_entry(struct vrend_decode_ctx * ctx,uint32_t offset)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 
get_buf_ptr(struct vrend_decode_ctx * ctx,uint32_t offset)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 
vrend_decode_create_shader(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_create_stream_output_target(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_set_framebuffer_state(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_framebuffer_state_no_attach(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_clear(struct vrend_decode_ctx * ctx,int length)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 
uif(unsigned int ui)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 
vrend_decode_set_viewport_state(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_index_buffer(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_constant_buffer(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_set_uniform_buffer(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_vertex_buffers(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_set_sampler_views(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_resource_inline_write(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_draw_vbo(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_create_blend(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_create_dsa(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_create_rasterizer(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_create_surface(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_create_sampler_view(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_create_sampler_state(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_create_ve(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_create_query(struct vrend_decode_ctx * ctx,uint32_t handle,uint16_t length)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 
vrend_decode_create_object(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_bind_object(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_destroy_object(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_stencil_ref(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_blend_color(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_scissor_state(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_polygon_stipple(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_clip_state(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_sample_mask(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_min_samples(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_resource_copy_region(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_blit(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_bind_sampler_states(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_begin_query(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_end_query(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_get_query_result(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_render_condition(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_sub_ctx(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_create_sub_ctx(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_destroy_sub_ctx(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_bind_shader(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_tess_state(struct vrend_decode_ctx * ctx,int length)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 
vrend_decode_set_shader_buffers(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_set_shader_images(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_memory_barrier(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_launch_grid(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_set_streamout_targets(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_decode_texture_barrier(struct vrend_decode_ctx * ctx,uint16_t length)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 
vrend_renderer_context_create_internal(uint32_t handle,uint32_t nlen,const char * debug_name)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 
vrend_renderer_context_create(uint32_t handle,uint32_t nlen,const char * debug_name)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 
vrend_renderer_context_destroy(uint32_t handle)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 
vrend_lookup_renderer_ctx(uint32_t ctx_id)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 
vrend_decode_block(uint32_t ctx_id,uint32_t * block,int ndw)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 
vrend_decode_reset(bool ctx_0_only)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