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