xref: /aosp_15_r20/external/virglrenderer/src/vrend_decode.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
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 #include <fcntl.h>
30 
31 #include "util/u_memory.h"
32 #include "pipe/p_defines.h"
33 #include "pipe/p_state.h"
34 #include "pipe/p_shader_tokens.h"
35 #include "virgl_context.h"
36 #include "virgl_resource.h"
37 #include "vrend_renderer.h"
38 #include "vrend_object.h"
39 #include "tgsi/tgsi_text.h"
40 #include "vrend_debug.h"
41 #include "vrend_tweaks.h"
42 #include "virgl_util.h"
43 
44 #ifdef ENABLE_VIDEO
45 #include "vrend_video.h"
46 #endif
47 
48 /* decode side */
49 #define DECODE_MAX_TOKENS 8000
50 
51 struct vrend_decode_ctx {
52    struct virgl_context base;
53    struct vrend_context *grctx;
54 };
55 
get_buf_entry(const uint32_t * buf,uint32_t offset)56 static inline uint32_t get_buf_entry(const uint32_t *buf, uint32_t offset)
57 {
58    return buf[offset];
59 }
60 
get_buf_ptr(const uint32_t * buf,uint32_t offset)61 static inline const void *get_buf_ptr(const uint32_t *buf, uint32_t offset)
62 {
63    return &buf[offset];
64 }
65 
vrend_decode_create_shader(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)66 static int vrend_decode_create_shader(struct vrend_context *ctx,
67                                       const uint32_t *buf,
68                                       uint32_t handle,
69                                       uint16_t length)
70 {
71    struct pipe_stream_output_info so_info;
72    uint i;
73    int ret;
74    uint32_t shader_offset, req_local_mem = 0;
75    unsigned num_tokens, num_so_outputs, offlen;
76    const uint8_t *shd_text;
77    uint32_t type;
78 
79    if (length < VIRGL_OBJ_SHADER_HDR_SIZE(0))
80       return EINVAL;
81 
82    type = get_buf_entry(buf, VIRGL_OBJ_SHADER_TYPE);
83    num_tokens = get_buf_entry(buf, VIRGL_OBJ_SHADER_NUM_TOKENS);
84    offlen = get_buf_entry(buf, VIRGL_OBJ_SHADER_OFFSET);
85 
86    if (type == PIPE_SHADER_COMPUTE) {
87       req_local_mem = get_buf_entry(buf, VIRGL_OBJ_SHADER_SO_NUM_OUTPUTS);
88       num_so_outputs = 0;
89    } else {
90       num_so_outputs = get_buf_entry(buf, VIRGL_OBJ_SHADER_SO_NUM_OUTPUTS);
91       if (length < VIRGL_OBJ_SHADER_HDR_SIZE(num_so_outputs))
92          return EINVAL;
93 
94       if (num_so_outputs > PIPE_MAX_SO_OUTPUTS)
95          return EINVAL;
96    }
97 
98    shader_offset = 6;
99    if (num_so_outputs) {
100       so_info.num_outputs = num_so_outputs;
101       if (so_info.num_outputs) {
102          for (i = 0; i < 4; i++)
103             so_info.stride[i] = get_buf_entry(buf, VIRGL_OBJ_SHADER_SO_STRIDE(i));
104          for (i = 0; i < so_info.num_outputs; i++) {
105             uint32_t tmp = get_buf_entry(buf, VIRGL_OBJ_SHADER_SO_OUTPUT0(i));
106 
107             so_info.output[i].register_index = tmp & 0xff;
108             so_info.output[i].start_component = (tmp >> 8) & 0x3;
109             so_info.output[i].num_components = (tmp >> 10) & 0x7;
110             so_info.output[i].output_buffer = (tmp >> 13) & 0x7;
111             so_info.output[i].dst_offset = (tmp >> 16) & 0xffff;
112             tmp = get_buf_entry(buf, VIRGL_OBJ_SHADER_SO_OUTPUT0_SO(i));
113             so_info.output[i].stream = (tmp & 0x3);
114             so_info.output[i].need_temp = so_info.output[i].num_components < 4;
115          }
116 
117          for (i = 0; i < so_info.num_outputs - 1; i++) {
118             for (unsigned j = i + 1; j < so_info.num_outputs; j++) {
119                so_info.output[j].need_temp |=
120                      (so_info.output[i].register_index == so_info.output[j].register_index);
121             }
122          }
123       }
124       shader_offset += 4 + (2 * num_so_outputs);
125    } else
126      memset(&so_info, 0, sizeof(so_info));
127 
128    shd_text = get_buf_ptr(buf, shader_offset);
129    ret = vrend_create_shader(ctx, handle, &so_info, req_local_mem, (const char *)shd_text, offlen, num_tokens, type, length - shader_offset + 1);
130 
131    return ret;
132 }
133 
vrend_decode_create_stream_output_target(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)134 static int vrend_decode_create_stream_output_target(struct vrend_context *ctx, const uint32_t *buf,
135                                                     uint32_t handle, uint16_t length)
136 {
137    uint32_t res_handle, buffer_size, buffer_offset;
138 
139    if (length != VIRGL_OBJ_STREAMOUT_SIZE)
140       return EINVAL;
141 
142    res_handle = get_buf_entry(buf, VIRGL_OBJ_STREAMOUT_RES_HANDLE);
143    buffer_offset = get_buf_entry(buf, VIRGL_OBJ_STREAMOUT_BUFFER_OFFSET);
144    buffer_size = get_buf_entry(buf, VIRGL_OBJ_STREAMOUT_BUFFER_SIZE);
145 
146    return vrend_create_so_target(ctx, handle, res_handle, buffer_offset,
147                                  buffer_size);
148 }
149 
vrend_decode_set_framebuffer_state(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)150 static int vrend_decode_set_framebuffer_state(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
151 {
152    if (length < 2)
153       return EINVAL;
154 
155    uint32_t nr_cbufs = get_buf_entry(buf, VIRGL_SET_FRAMEBUFFER_STATE_NR_CBUFS);
156    uint32_t zsurf_handle = get_buf_entry(buf, VIRGL_SET_FRAMEBUFFER_STATE_NR_ZSURF_HANDLE);
157    uint32_t surf_handle[8];
158    uint32_t i;
159 
160    if (length != (2u + nr_cbufs))
161       return EINVAL;
162 
163    if (nr_cbufs > 8)
164       return EINVAL;
165 
166    for (i = 0; i < nr_cbufs; i++)
167       surf_handle[i] = get_buf_entry(buf, VIRGL_SET_FRAMEBUFFER_STATE_CBUF_HANDLE(i));
168    vrend_set_framebuffer_state(ctx, nr_cbufs, surf_handle, zsurf_handle);
169    return 0;
170 }
171 
vrend_decode_set_framebuffer_state_no_attach(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)172 static int vrend_decode_set_framebuffer_state_no_attach(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
173 {
174    uint32_t width, height;
175    uint32_t layers, samples;
176    uint32_t tmp;
177 
178    if (length != VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_SIZE)
179       return EINVAL;
180 
181    tmp = get_buf_entry(buf, VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_WIDTH_HEIGHT);
182    width = VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_WIDTH(tmp);
183    height = VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_HEIGHT(tmp);
184 
185    tmp = get_buf_entry(buf, VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_LAYERS_SAMPLES);
186    layers = VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_LAYERS(tmp);
187    samples = VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_SAMPLES(tmp);
188 
189    vrend_set_framebuffer_state_no_attach(ctx, width, height, layers, samples);
190    return 0;
191 }
192 
vrend_decode_clear(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)193 static int vrend_decode_clear(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
194 {
195    union pipe_color_union color;
196    double depth;
197    unsigned stencil, buffers;
198    int i;
199 
200    if (length != VIRGL_OBJ_CLEAR_SIZE)
201       return EINVAL;
202    buffers = get_buf_entry(buf, VIRGL_OBJ_CLEAR_BUFFERS);
203    for (i = 0; i < 4; i++)
204       color.ui[i] = get_buf_entry(buf, VIRGL_OBJ_CLEAR_COLOR_0 + i);
205    const void *depth_ptr = get_buf_ptr(buf, VIRGL_OBJ_CLEAR_DEPTH_0);
206    memcpy(&depth, depth_ptr, sizeof(double));
207    stencil = get_buf_entry(buf, VIRGL_OBJ_CLEAR_STENCIL);
208 
209    vrend_clear(ctx, buffers, &color, depth, stencil);
210    return 0;
211 }
212 
vrend_decode_clear_texture(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)213 static int vrend_decode_clear_texture(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
214 {
215    struct pipe_box box;
216    uint32_t handle;
217    uint32_t level;
218    uint32_t arr[4] = {0};
219 
220    if (length != VIRGL_CLEAR_TEXTURE_SIZE)
221       return EINVAL;
222 
223    handle = get_buf_entry(buf, VIRGL_TEXTURE_HANDLE);
224    level = get_buf_entry(buf, VIRGL_TEXTURE_LEVEL);
225    box.x = get_buf_entry(buf, VIRGL_TEXTURE_SRC_X);
226    box.y = get_buf_entry(buf, VIRGL_TEXTURE_SRC_Y);
227    box.z = get_buf_entry(buf, VIRGL_TEXTURE_SRC_Z);
228    box.width = get_buf_entry(buf, VIRGL_TEXTURE_SRC_W);
229    box.height = get_buf_entry(buf, VIRGL_TEXTURE_SRC_H);
230    box.depth = get_buf_entry(buf, VIRGL_TEXTURE_SRC_D);
231    arr[0] = get_buf_entry(buf, VIRGL_TEXTURE_ARRAY_A);
232    arr[1] = get_buf_entry(buf, VIRGL_TEXTURE_ARRAY_B);
233    arr[2] = get_buf_entry(buf, VIRGL_TEXTURE_ARRAY_C);
234    arr[3] = get_buf_entry(buf, VIRGL_TEXTURE_ARRAY_D);
235 
236    return vrend_clear_texture(ctx, handle, level, &box, (void *) &arr);
237 }
238 
vrend_decode_set_viewport_state(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)239 static int vrend_decode_set_viewport_state(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
240 {
241    struct pipe_viewport_state vps[PIPE_MAX_VIEWPORTS];
242    uint i, v;
243    uint32_t num_viewports, start_slot;
244    if (length < 1)
245       return EINVAL;
246 
247    if ((length - 1) % 6)
248       return EINVAL;
249 
250    num_viewports = (length - 1) / 6;
251    start_slot = get_buf_entry(buf, VIRGL_SET_VIEWPORT_START_SLOT);
252 
253    if (num_viewports > PIPE_MAX_VIEWPORTS ||
254        start_slot > (PIPE_MAX_VIEWPORTS - num_viewports))
255       return EINVAL;
256 
257    for (v = 0; v < num_viewports; v++) {
258       for (i = 0; i < 3; i++)
259          vps[v].scale[i] = uif(get_buf_entry(buf, VIRGL_SET_VIEWPORT_STATE_SCALE_0(v) + i));
260       for (i = 0; i < 3; i++)
261          vps[v].translate[i] = uif(get_buf_entry(buf, VIRGL_SET_VIEWPORT_STATE_TRANSLATE_0(v) + i));
262    }
263 
264    vrend_set_viewport_states(ctx, start_slot, num_viewports, vps);
265    return 0;
266 }
267 
vrend_decode_set_index_buffer(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)268 static int vrend_decode_set_index_buffer(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
269 {
270    if (length != 1 && length != 3)
271       return EINVAL;
272    vrend_set_index_buffer(ctx,
273                           get_buf_entry(buf, VIRGL_SET_INDEX_BUFFER_HANDLE),
274                           (length == 3) ? get_buf_entry(buf, VIRGL_SET_INDEX_BUFFER_INDEX_SIZE) : 0,
275                           (length == 3) ? get_buf_entry(buf, VIRGL_SET_INDEX_BUFFER_OFFSET) : 0);
276    return 0;
277 }
278 
vrend_decode_set_constant_buffer(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)279 static int vrend_decode_set_constant_buffer(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
280 {
281    uint32_t shader;
282    int nc = (length - 2);
283 
284    if (length < 2)
285       return EINVAL;
286 
287    shader = get_buf_entry(buf, VIRGL_SET_CONSTANT_BUFFER_SHADER_TYPE);
288    /* VIRGL_SET_CONSTANT_BUFFER_INDEX is not used */
289 
290    if (shader >= PIPE_SHADER_TYPES)
291       return EINVAL;
292 
293    vrend_set_constants(ctx, shader, nc, get_buf_ptr(buf, VIRGL_SET_CONSTANT_BUFFER_DATA_START));
294    return 0;
295 }
296 
vrend_decode_set_uniform_buffer(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)297 static int vrend_decode_set_uniform_buffer(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
298 {
299    if (length != VIRGL_SET_UNIFORM_BUFFER_SIZE)
300       return EINVAL;
301 
302    uint32_t shader = get_buf_entry(buf, VIRGL_SET_UNIFORM_BUFFER_SHADER_TYPE);
303    uint32_t index = get_buf_entry(buf, VIRGL_SET_UNIFORM_BUFFER_INDEX);
304    uint32_t offset = get_buf_entry(buf, VIRGL_SET_UNIFORM_BUFFER_OFFSET);
305    uint32_t blength = get_buf_entry(buf, VIRGL_SET_UNIFORM_BUFFER_LENGTH);
306    uint32_t handle = get_buf_entry(buf, VIRGL_SET_UNIFORM_BUFFER_RES_HANDLE);
307 
308    if (shader >= PIPE_SHADER_TYPES)
309       return EINVAL;
310 
311    if (index >= PIPE_MAX_CONSTANT_BUFFERS)
312       return EINVAL;
313 
314    vrend_set_uniform_buffer(ctx, shader, index, offset, blength, handle);
315    return 0;
316 }
317 
vrend_decode_set_vertex_buffers(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)318 static int vrend_decode_set_vertex_buffers(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
319 {
320    int num_vbo;
321    int i;
322 
323    /* must be a multiple of 3 */
324    if (length && (length % 3))
325       return EINVAL;
326 
327    num_vbo = (length / 3);
328    if (num_vbo > PIPE_MAX_ATTRIBS)
329       return EINVAL;
330 
331    for (i = 0; i < num_vbo; i++) {
332       vrend_set_single_vbo(ctx, i,
333                            get_buf_entry(buf, VIRGL_SET_VERTEX_BUFFER_STRIDE(i)),
334                            get_buf_entry(buf, VIRGL_SET_VERTEX_BUFFER_OFFSET(i)),
335                            get_buf_entry(buf, VIRGL_SET_VERTEX_BUFFER_HANDLE(i)));
336    }
337    vrend_set_num_vbo(ctx, num_vbo);
338    return 0;
339 }
340 
vrend_decode_set_sampler_views(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)341 static int vrend_decode_set_sampler_views(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
342 {
343    uint32_t num_samps;
344    uint32_t i;
345    uint32_t shader_type;
346    uint32_t start_slot;
347 
348    if (length < 2)
349       return EINVAL;
350    num_samps = length - 2;
351    shader_type = get_buf_entry(buf, VIRGL_SET_SAMPLER_VIEWS_SHADER_TYPE);
352    start_slot = get_buf_entry(buf, VIRGL_SET_SAMPLER_VIEWS_START_SLOT);
353 
354    if (shader_type >= PIPE_SHADER_TYPES)
355       return EINVAL;
356 
357    if (num_samps > PIPE_MAX_SHADER_SAMPLER_VIEWS ||
358        start_slot > (PIPE_MAX_SHADER_SAMPLER_VIEWS - num_samps))
359       return EINVAL;
360 
361    for (i = 0; i < num_samps; i++) {
362       uint32_t handle = get_buf_entry(buf, VIRGL_SET_SAMPLER_VIEWS_V0_HANDLE + i);
363       vrend_set_single_sampler_view(ctx, shader_type, i + start_slot, handle);
364    }
365    vrend_set_num_sampler_views(ctx, shader_type, start_slot, num_samps);
366    return 0;
367 }
368 
vrend_decode_transfer_common(const uint32_t * buf,uint32_t * dst_handle,struct vrend_transfer_info * info)369 static void vrend_decode_transfer_common(const uint32_t *buf,
370                                          uint32_t *dst_handle,
371                                          struct vrend_transfer_info *info)
372 {
373    *dst_handle = get_buf_entry(buf, VIRGL_RESOURCE_IW_RES_HANDLE);
374 
375    info->level = get_buf_entry(buf, VIRGL_RESOURCE_IW_LEVEL);
376    info->stride = get_buf_entry(buf, VIRGL_RESOURCE_IW_STRIDE);
377    info->layer_stride = get_buf_entry(buf, VIRGL_RESOURCE_IW_LAYER_STRIDE);
378    info->box->x = get_buf_entry(buf, VIRGL_RESOURCE_IW_X);
379    info->box->y = get_buf_entry(buf, VIRGL_RESOURCE_IW_Y);
380    info->box->z = get_buf_entry(buf, VIRGL_RESOURCE_IW_Z);
381    info->box->width = get_buf_entry(buf, VIRGL_RESOURCE_IW_W);
382    info->box->height = get_buf_entry(buf, VIRGL_RESOURCE_IW_H);
383    info->box->depth = get_buf_entry(buf, VIRGL_RESOURCE_IW_D);
384 }
385 
vrend_decode_resource_inline_write(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)386 static int vrend_decode_resource_inline_write(struct vrend_context *ctx, const uint32_t *buf,
387                                               uint32_t length)
388 {
389    struct pipe_box box;
390    uint32_t dst_handle;
391    struct vrend_transfer_info info;
392    uint32_t data_len;
393    struct iovec dataiovec;
394    const void *data;
395 
396    if (length < 12)
397       return EINVAL;
398 
399    memset(&info, 0, sizeof(info));
400    info.box = &box;
401    vrend_decode_transfer_common(buf, &dst_handle, &info);
402    data_len = (length - 11) * 4;
403    data = get_buf_ptr(buf, VIRGL_RESOURCE_IW_DATA_START);
404 
405    info.offset = 0;
406 
407    dataiovec.iov_base = (void*)data;
408    dataiovec.iov_len = data_len;
409 
410    info.iovec = &dataiovec;
411    info.iovec_cnt = 1;
412    return vrend_transfer_inline_write(ctx, dst_handle, &info);
413 }
414 
vrend_decode_draw_vbo(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)415 static int vrend_decode_draw_vbo(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
416 {
417    struct pipe_draw_info info;
418    uint32_t cso;
419    uint32_t handle = 0, indirect_draw_count_handle = 0;
420    if (length != VIRGL_DRAW_VBO_SIZE && length != VIRGL_DRAW_VBO_SIZE_TESS &&
421        length != VIRGL_DRAW_VBO_SIZE_INDIRECT)
422       return EINVAL;
423    memset(&info, 0, sizeof(struct pipe_draw_info));
424 
425    info.start = get_buf_entry(buf, VIRGL_DRAW_VBO_START);
426    info.count = get_buf_entry(buf, VIRGL_DRAW_VBO_COUNT);
427    info.mode = get_buf_entry(buf, VIRGL_DRAW_VBO_MODE);
428    info.indexed = !!get_buf_entry(buf, VIRGL_DRAW_VBO_INDEXED);
429    info.instance_count = get_buf_entry(buf, VIRGL_DRAW_VBO_INSTANCE_COUNT);
430    info.index_bias = get_buf_entry(buf, VIRGL_DRAW_VBO_INDEX_BIAS);
431    info.start_instance = get_buf_entry(buf, VIRGL_DRAW_VBO_START_INSTANCE);
432    info.primitive_restart = !!get_buf_entry(buf, VIRGL_DRAW_VBO_PRIMITIVE_RESTART);
433    info.restart_index = get_buf_entry(buf, VIRGL_DRAW_VBO_RESTART_INDEX);
434    info.min_index = get_buf_entry(buf, VIRGL_DRAW_VBO_MIN_INDEX);
435    info.max_index = get_buf_entry(buf, VIRGL_DRAW_VBO_MAX_INDEX);
436 
437    if (length >= VIRGL_DRAW_VBO_SIZE_TESS) {
438       info.vertices_per_patch = get_buf_entry(buf, VIRGL_DRAW_VBO_VERTICES_PER_PATCH);
439       info.drawid = get_buf_entry(buf, VIRGL_DRAW_VBO_DRAWID);
440    }
441 
442    if (length == VIRGL_DRAW_VBO_SIZE_INDIRECT) {
443       handle = get_buf_entry(buf, VIRGL_DRAW_VBO_INDIRECT_HANDLE);
444       info.indirect.offset = get_buf_entry(buf, VIRGL_DRAW_VBO_INDIRECT_OFFSET);
445       info.indirect.stride = get_buf_entry(buf, VIRGL_DRAW_VBO_INDIRECT_STRIDE);
446       info.indirect.draw_count = get_buf_entry(buf, VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT);
447       info.indirect.indirect_draw_count_offset = get_buf_entry(buf, VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_OFFSET);
448       indirect_draw_count_handle = get_buf_entry(buf, VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_HANDLE);
449    }
450 
451    cso = get_buf_entry(buf, VIRGL_DRAW_VBO_COUNT_FROM_SO);
452 
453    return vrend_draw_vbo(ctx, &info, cso, handle, indirect_draw_count_handle);
454 }
455 
vrend_decode_create_blend(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)456 static int vrend_decode_create_blend(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
457 {
458    struct pipe_blend_state *blend_state;
459    uint32_t tmp;
460    int i;
461 
462    if (length != VIRGL_OBJ_BLEND_SIZE) {
463       return EINVAL;
464    }
465 
466    blend_state = CALLOC_STRUCT(pipe_blend_state);
467    if (!blend_state)
468       return ENOMEM;
469 
470    tmp = get_buf_entry(buf, VIRGL_OBJ_BLEND_S0);
471    blend_state->independent_blend_enable = (tmp & 1);
472    blend_state->logicop_enable = (tmp >> 1) & 0x1;
473    blend_state->dither = (tmp >> 2) & 0x1;
474    blend_state->alpha_to_coverage = (tmp >> 3) & 0x1;
475    blend_state->alpha_to_one = (tmp >> 4) & 0x1;
476 
477    tmp = get_buf_entry(buf, VIRGL_OBJ_BLEND_S1);
478    blend_state->logicop_func = tmp & 0xf;
479 
480    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
481       tmp = get_buf_entry(buf, VIRGL_OBJ_BLEND_S2(i));
482       blend_state->rt[i].blend_enable = tmp & 0x1;
483       blend_state->rt[i].rgb_func = (tmp >> 1) & 0x7;
484       blend_state->rt[i].rgb_src_factor = (tmp >> 4) & 0x1f;
485       blend_state->rt[i].rgb_dst_factor = (tmp >> 9) & 0x1f;
486       blend_state->rt[i].alpha_func = (tmp >> 14) & 0x7;
487       blend_state->rt[i].alpha_src_factor = (tmp >> 17) & 0x1f;
488       blend_state->rt[i].alpha_dst_factor = (tmp >> 22) & 0x1f;
489       blend_state->rt[i].colormask = (tmp >> 27) & 0xf;
490    }
491 
492    tmp = vrend_renderer_object_insert(ctx, blend_state, handle,
493                                       VIRGL_OBJECT_BLEND);
494    if (tmp == 0) {
495       FREE(blend_state);
496       return ENOMEM;
497    }
498    return 0;
499 }
500 
vrend_decode_create_dsa(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)501 static int vrend_decode_create_dsa(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
502 {
503    int i;
504    struct pipe_depth_stencil_alpha_state *dsa_state;
505    uint32_t tmp;
506 
507    if (length != VIRGL_OBJ_DSA_SIZE)
508       return EINVAL;
509 
510    dsa_state = CALLOC_STRUCT(pipe_depth_stencil_alpha_state);
511    if (!dsa_state)
512       return ENOMEM;
513 
514    tmp = get_buf_entry(buf, VIRGL_OBJ_DSA_S0);
515    dsa_state->depth.enabled = tmp & 0x1;
516    dsa_state->depth.writemask = (tmp >> 1) & 0x1;
517    dsa_state->depth.func = (tmp >> 2) & 0x7;
518 
519    dsa_state->alpha.enabled = (tmp >> 8) & 0x1;
520    dsa_state->alpha.func = (tmp >> 9) & 0x7;
521 
522    for (i = 0; i < 2; i++) {
523       tmp = get_buf_entry(buf, VIRGL_OBJ_DSA_S1 + i);
524       dsa_state->stencil[i].enabled = tmp & 0x1;
525       dsa_state->stencil[i].func = (tmp >> 1) & 0x7;
526       dsa_state->stencil[i].fail_op = (tmp >> 4) & 0x7;
527       dsa_state->stencil[i].zpass_op = (tmp >> 7) & 0x7;
528       dsa_state->stencil[i].zfail_op = (tmp >> 10) & 0x7;
529       dsa_state->stencil[i].valuemask = (tmp >> 13) & 0xff;
530       dsa_state->stencil[i].writemask = (tmp >> 21) & 0xff;
531    }
532 
533    tmp = get_buf_entry(buf, VIRGL_OBJ_DSA_ALPHA_REF);
534    dsa_state->alpha.ref_value = uif(tmp);
535 
536    tmp = vrend_renderer_object_insert(ctx, dsa_state, handle,
537                                       VIRGL_OBJECT_DSA);
538    if (tmp == 0) {
539       FREE(dsa_state);
540       return ENOMEM;
541    }
542    return 0;
543 }
544 
vrend_decode_create_rasterizer(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)545 static int vrend_decode_create_rasterizer(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
546 {
547    struct pipe_rasterizer_state *rs_state;
548    uint32_t tmp;
549 
550    if (length != VIRGL_OBJ_RS_SIZE)
551       return EINVAL;
552 
553    rs_state = CALLOC_STRUCT(pipe_rasterizer_state);
554    if (!rs_state)
555       return ENOMEM;
556 
557    tmp = get_buf_entry(buf, VIRGL_OBJ_RS_S0);
558 #define ebit(name, bit) rs_state->name = (tmp >> bit) & 0x1
559 #define emask(name, bit, mask) rs_state->name = (tmp >> bit) & mask
560 
561    ebit(flatshade, 0);
562    ebit(depth_clip, 1);
563    ebit(clip_halfz, 2);
564    ebit(rasterizer_discard, 3);
565    ebit(flatshade_first, 4);
566    ebit(light_twoside, 5);
567    ebit(sprite_coord_mode, 6);
568    ebit(point_quad_rasterization, 7);
569    emask(cull_face, 8, 0x3);
570    emask(fill_front, 10, 0x3);
571    emask(fill_back, 12, 0x3);
572    ebit(scissor, 14);
573    ebit(front_ccw, 15);
574    ebit(clamp_vertex_color, 16);
575    ebit(clamp_fragment_color, 17);
576    ebit(offset_line, 18);
577    ebit(offset_point, 19);
578    ebit(offset_tri, 20);
579    ebit(poly_smooth, 21);
580    ebit(poly_stipple_enable, 22);
581    ebit(point_smooth, 23);
582    ebit(point_size_per_vertex, 24);
583    ebit(multisample, 25);
584    ebit(line_smooth, 26);
585    ebit(line_stipple_enable, 27);
586    ebit(line_last_pixel, 28);
587    ebit(half_pixel_center, 29);
588    ebit(bottom_edge_rule, 30);
589    ebit(force_persample_interp, 31);
590    rs_state->point_size = uif(get_buf_entry(buf, VIRGL_OBJ_RS_POINT_SIZE));
591    rs_state->sprite_coord_enable = get_buf_entry(buf, VIRGL_OBJ_RS_SPRITE_COORD_ENABLE);
592    tmp = get_buf_entry(buf, VIRGL_OBJ_RS_S3);
593    emask(line_stipple_pattern, 0, 0xffff);
594    emask(line_stipple_factor, 16, 0xff);
595    emask(clip_plane_enable, 24, 0xff);
596 
597    rs_state->line_width = uif(get_buf_entry(buf, VIRGL_OBJ_RS_LINE_WIDTH));
598    rs_state->offset_units = uif(get_buf_entry(buf, VIRGL_OBJ_RS_OFFSET_UNITS));
599    rs_state->offset_scale = uif(get_buf_entry(buf, VIRGL_OBJ_RS_OFFSET_SCALE));
600    rs_state->offset_clamp = uif(get_buf_entry(buf, VIRGL_OBJ_RS_OFFSET_CLAMP));
601 
602    tmp = vrend_renderer_object_insert(ctx, rs_state, handle,
603                                       VIRGL_OBJECT_RASTERIZER);
604    if (tmp == 0) {
605       FREE(rs_state);
606       return ENOMEM;
607    }
608    return 0;
609 }
610 
vrend_decode_create_surface_common(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint32_t sample_count)611 static int vrend_decode_create_surface_common(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint32_t sample_count)
612 {
613    uint32_t res_handle, format, val0, val1;
614 
615    res_handle = get_buf_entry(buf, VIRGL_OBJ_SURFACE_RES_HANDLE);
616    format = get_buf_entry(buf, VIRGL_OBJ_SURFACE_FORMAT);
617    /* decide later if these are texture or buffer */
618    val0 = get_buf_entry(buf, VIRGL_OBJ_SURFACE_BUFFER_FIRST_ELEMENT);
619    val1 = get_buf_entry(buf, VIRGL_OBJ_SURFACE_BUFFER_LAST_ELEMENT);
620 
621    return vrend_create_surface(ctx, handle, res_handle, format, val0, val1, sample_count);
622 }
623 
vrend_decode_create_surface(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)624 static int vrend_decode_create_surface(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
625 {
626    if (length != VIRGL_OBJ_SURFACE_SIZE)
627       return EINVAL;
628 
629    return vrend_decode_create_surface_common(ctx, buf, handle, 0);
630 }
631 
vrend_decode_create_msaa_surface(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)632 static int vrend_decode_create_msaa_surface(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
633 {
634    if (length != VIRGL_OBJ_MSAA_SURFACE_SIZE)
635       return EINVAL;
636 
637    uint32_t sample_count = get_buf_entry(buf, VIRGL_OBJ_SURFACE_SAMPLE_COUNT);
638    return vrend_decode_create_surface_common(ctx, buf, handle, sample_count);
639 }
640 
vrend_decode_create_sampler_view(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)641 static int vrend_decode_create_sampler_view(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
642 {
643    uint32_t res_handle, format, val0, val1, swizzle_packed;
644 
645    if (length != VIRGL_OBJ_SAMPLER_VIEW_SIZE)
646       return EINVAL;
647 
648    res_handle = get_buf_entry(buf, VIRGL_OBJ_SAMPLER_VIEW_RES_HANDLE);
649    format = get_buf_entry(buf, VIRGL_OBJ_SAMPLER_VIEW_FORMAT);
650    val0 = get_buf_entry(buf, VIRGL_OBJ_SAMPLER_VIEW_BUFFER_FIRST_ELEMENT);
651    val1 = get_buf_entry(buf, VIRGL_OBJ_SAMPLER_VIEW_BUFFER_LAST_ELEMENT);
652    swizzle_packed = get_buf_entry(buf, VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE);
653    return vrend_create_sampler_view(ctx, handle, res_handle, format, val0, val1,swizzle_packed);
654 }
655 
vrend_decode_create_sampler_state(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)656 static int vrend_decode_create_sampler_state(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
657 {
658    struct pipe_sampler_state state;
659    int i;
660    uint32_t tmp;
661 
662    if (length != VIRGL_OBJ_SAMPLER_STATE_SIZE)
663       return EINVAL;
664    tmp = get_buf_entry(buf, VIRGL_OBJ_SAMPLER_STATE_S0);
665    state.wrap_s = tmp & 0x7;
666    state.wrap_t = (tmp >> 3) & 0x7;
667    state.wrap_r = (tmp >> 6) & 0x7;
668    state.min_img_filter = (tmp >> 9) & 0x3;
669    state.min_mip_filter = (tmp >> 11) & 0x3;
670    state.mag_img_filter = (tmp >> 13) & 0x3;
671    state.compare_mode = (tmp >> 15) & 0x1;
672    state.compare_func = (tmp >> 16) & 0x7;
673    state.seamless_cube_map = (tmp >> 19) & 0x1;
674    state.max_anisotropy = (float)((tmp >> 20) & 0x3f);
675    state.normalized_coords = 0;
676 
677    state.lod_bias = uif(get_buf_entry(buf, VIRGL_OBJ_SAMPLER_STATE_LOD_BIAS));
678    state.min_lod = uif(get_buf_entry(buf, VIRGL_OBJ_SAMPLER_STATE_MIN_LOD));
679    state.max_lod = uif(get_buf_entry(buf, VIRGL_OBJ_SAMPLER_STATE_MAX_LOD));
680 
681    for (i = 0; i < 4; i++)
682       state.border_color.ui[i] = get_buf_entry(buf, VIRGL_OBJ_SAMPLER_STATE_BORDER_COLOR(i));
683 
684    if (state.min_mip_filter != PIPE_TEX_MIPFILTER_NONE &&
685        state.min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR &&
686        state.min_mip_filter != PIPE_TEX_MIPFILTER_NEAREST)
687      return EINVAL;
688 
689    return vrend_create_sampler_state(ctx, handle, &state);
690 }
691 
vrend_decode_create_ve(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)692 static int vrend_decode_create_ve(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
693 {
694    struct pipe_vertex_element *ve = NULL;
695    int num_elements;
696    int i;
697    int ret;
698 
699    if (length < 1)
700       return EINVAL;
701 
702    if ((length - 1) % 4)
703       return EINVAL;
704 
705    num_elements = (length - 1) / 4;
706 
707    if (num_elements) {
708       ve = calloc(num_elements, sizeof(struct pipe_vertex_element));
709 
710       if (!ve)
711          return ENOMEM;
712 
713       for (i = 0; i < num_elements; i++) {
714          ve[i].src_offset = get_buf_entry(buf, VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_OFFSET(i));
715          ve[i].instance_divisor = get_buf_entry(buf, VIRGL_OBJ_VERTEX_ELEMENTS_V0_INSTANCE_DIVISOR(i));
716          ve[i].vertex_buffer_index = get_buf_entry(buf, VIRGL_OBJ_VERTEX_ELEMENTS_V0_VERTEX_BUFFER_INDEX(i));
717 
718          if (ve[i].vertex_buffer_index >= PIPE_MAX_ATTRIBS) {
719             FREE(ve);
720             return EINVAL;
721          }
722 
723          ve[i].src_format = get_buf_entry(buf, VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_FORMAT(i));
724       }
725    }
726 
727    ret = vrend_create_vertex_elements_state(ctx, handle, num_elements, ve);
728 
729    FREE(ve);
730    return ret;
731 }
732 
vrend_decode_create_query(struct vrend_context * ctx,const uint32_t * buf,uint32_t handle,uint16_t length)733 static int vrend_decode_create_query(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
734 {
735    uint32_t query_type;
736    uint32_t query_index;
737    uint32_t res_handle;
738    uint32_t offset;
739    uint32_t tmp;
740 
741    if (length != VIRGL_OBJ_QUERY_SIZE)
742       return EINVAL;
743 
744    tmp = get_buf_entry(buf, VIRGL_OBJ_QUERY_TYPE_INDEX);
745    query_type = VIRGL_OBJ_QUERY_TYPE(tmp);
746    query_index = (tmp >> 16) & 0xffff;
747 
748    offset = get_buf_entry(buf, VIRGL_OBJ_QUERY_OFFSET);
749    res_handle = get_buf_entry(buf, VIRGL_OBJ_QUERY_RES_HANDLE);
750 
751    return vrend_create_query(ctx, handle, query_type, query_index, res_handle, offset);
752 }
753 
vrend_decode_create_object(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)754 static int vrend_decode_create_object(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
755 {
756    if (length < 1)
757       return EINVAL;
758 
759    uint32_t header = get_buf_entry(buf, VIRGL_OBJ_CREATE_HEADER);
760    uint32_t handle = get_buf_entry(buf, VIRGL_OBJ_CREATE_HANDLE);
761    uint8_t obj_type = (header >> 8) & 0xff;
762    int ret = 0;
763 
764    if (handle == 0)
765       return EINVAL;
766 
767    VREND_DEBUG(dbg_object, ctx,"  CREATE %-18s handle:0x%x len:%d\n",
768                vrend_get_object_type_name(obj_type), handle, length);
769 
770    TRACE_SCOPE(vrend_get_object_type_name(obj_type));
771 
772    switch (obj_type){
773    case VIRGL_OBJECT_BLEND:
774       ret = vrend_decode_create_blend(ctx, buf, handle, length);
775       break;
776    case VIRGL_OBJECT_DSA:
777       ret = vrend_decode_create_dsa(ctx, buf, handle, length);
778       break;
779    case VIRGL_OBJECT_RASTERIZER:
780       ret = vrend_decode_create_rasterizer(ctx, buf, handle, length);
781       break;
782    case VIRGL_OBJECT_SHADER:
783       ret = vrend_decode_create_shader(ctx, buf, handle, length);
784       break;
785    case VIRGL_OBJECT_VERTEX_ELEMENTS:
786       ret = vrend_decode_create_ve(ctx, buf, handle, length);
787       break;
788    case VIRGL_OBJECT_SURFACE:
789       ret = vrend_decode_create_surface(ctx, buf, handle, length);
790       break;
791    case VIRGL_OBJECT_SAMPLER_VIEW:
792       ret = vrend_decode_create_sampler_view(ctx, buf, handle, length);
793       break;
794    case VIRGL_OBJECT_SAMPLER_STATE:
795       ret = vrend_decode_create_sampler_state(ctx, buf, handle, length);
796       break;
797    case VIRGL_OBJECT_QUERY:
798       ret = vrend_decode_create_query(ctx, buf, handle, length);
799       break;
800    case VIRGL_OBJECT_STREAMOUT_TARGET:
801       ret = vrend_decode_create_stream_output_target(ctx, buf, handle, length);
802       break;
803    case VIRGL_OBJECT_MSAA_SURFACE:
804       ret = vrend_decode_create_msaa_surface(ctx, buf, handle, length);
805       break;
806    default:
807       return EINVAL;
808    }
809 
810    return ret;
811 }
812 
vrend_decode_bind_object(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)813 static int vrend_decode_bind_object(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
814 {
815    if (length != 1)
816       return EINVAL;
817 
818    uint32_t header = get_buf_entry(buf, VIRGL_OBJ_BIND_HEADER);
819    uint32_t handle = get_buf_entry(buf, VIRGL_OBJ_BIND_HANDLE);
820    uint8_t obj_type = (header >> 8) & 0xff;
821 
822    VREND_DEBUG(dbg_object, ctx,
823                "  BIND %-20s handle:0x%x len:%d\n",
824                vrend_get_object_type_name(obj_type), handle, length);
825 
826    switch (obj_type) {
827    case VIRGL_OBJECT_BLEND:
828       vrend_object_bind_blend(ctx, handle);
829       break;
830    case VIRGL_OBJECT_DSA:
831       vrend_object_bind_dsa(ctx, handle);
832       break;
833    case VIRGL_OBJECT_RASTERIZER:
834       vrend_object_bind_rasterizer(ctx, handle);
835       break;
836    case VIRGL_OBJECT_VERTEX_ELEMENTS:
837       vrend_bind_vertex_elements_state(ctx, handle);
838       break;
839    default:
840       return EINVAL;
841    }
842 
843    return 0;
844 }
845 
vrend_decode_destroy_object(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)846 static int vrend_decode_destroy_object(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
847 {
848    if (length != 1)
849       return EINVAL;
850 
851    uint32_t handle = get_buf_entry(buf, VIRGL_OBJ_DESTROY_HANDLE);
852 
853    VREND_DEBUG_EXT(dbg_object, ctx,
854                uint32_t obj = (get_buf_entry(buf, 0) >> 8) & 0xFF;
855                vrend_printf("  DESTROY %-17s handle:0x%x\n",
856                        vrend_get_object_type_name(obj), handle));
857 
858    vrend_renderer_object_destroy(ctx, handle);
859    return 0;
860 }
861 
vrend_decode_set_stencil_ref(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)862 static int vrend_decode_set_stencil_ref(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
863 {
864    if (length != VIRGL_SET_STENCIL_REF_SIZE)
865       return EINVAL;
866 
867    struct pipe_stencil_ref ref;
868    uint32_t val = get_buf_entry(buf, VIRGL_SET_STENCIL_REF);
869 
870    ref.ref_value[0] = val & 0xff;
871    ref.ref_value[1] = (val >> 8) & 0xff;
872    vrend_set_stencil_ref(ctx, &ref);
873    return 0;
874 }
875 
vrend_decode_set_blend_color(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)876 static int vrend_decode_set_blend_color(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
877 {
878    struct pipe_blend_color color;
879    int i;
880 
881    if (length != VIRGL_SET_BLEND_COLOR_SIZE)
882       return EINVAL;
883 
884    for (i = 0; i < 4; i++)
885       color.color[i] = uif(get_buf_entry(buf, VIRGL_SET_BLEND_COLOR(i)));
886 
887    vrend_set_blend_color(ctx, &color);
888    return 0;
889 }
890 
vrend_decode_set_scissor_state(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)891 static int vrend_decode_set_scissor_state(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
892 {
893    struct pipe_scissor_state ss[PIPE_MAX_VIEWPORTS];
894    uint32_t temp;
895    int32_t num_scissor;
896    uint32_t start_slot;
897    int s;
898    if (length < 1)
899       return EINVAL;
900 
901    if ((length - 1) % 2)
902       return EINVAL;
903 
904    num_scissor = (length - 1) / 2;
905    if (num_scissor > PIPE_MAX_VIEWPORTS)
906       return EINVAL;
907 
908    start_slot = get_buf_entry(buf, VIRGL_SET_SCISSOR_START_SLOT);
909 
910    for (s = 0; s < num_scissor; s++) {
911       temp = get_buf_entry(buf, VIRGL_SET_SCISSOR_MINX_MINY(s));
912       ss[s].minx = temp & 0xffff;
913       ss[s].miny = (temp >> 16) & 0xffff;
914 
915       temp = get_buf_entry(buf, VIRGL_SET_SCISSOR_MAXX_MAXY(s));
916       ss[s].maxx = temp & 0xffff;
917       ss[s].maxy = (temp >> 16) & 0xffff;
918    }
919 
920    vrend_set_scissor_state(ctx, start_slot, num_scissor, ss);
921    return 0;
922 }
923 
vrend_decode_set_polygon_stipple(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)924 static int vrend_decode_set_polygon_stipple(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
925 {
926    struct pipe_poly_stipple ps;
927    int i;
928 
929    if (length != VIRGL_POLYGON_STIPPLE_SIZE)
930       return EINVAL;
931 
932    for (i = 0; i < 32; i++)
933       ps.stipple[i] = get_buf_entry(buf, VIRGL_POLYGON_STIPPLE_P0 + i);
934 
935    vrend_set_polygon_stipple(ctx, &ps);
936    return 0;
937 }
938 
vrend_decode_set_clip_state(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)939 static int vrend_decode_set_clip_state(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
940 {
941    struct pipe_clip_state clip;
942    int i, j;
943 
944    if (length != VIRGL_SET_CLIP_STATE_SIZE)
945       return EINVAL;
946 
947    for (i = 0; i < 8; i++)
948       for (j = 0; j < 4; j++)
949          clip.ucp[i][j] = uif(get_buf_entry(buf, VIRGL_SET_CLIP_STATE_C0 + (i * 4) + j));
950    vrend_set_clip_state(ctx, &clip);
951    return 0;
952 }
953 
vrend_decode_set_sample_mask(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)954 static int vrend_decode_set_sample_mask(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
955 {
956    unsigned mask;
957 
958    if (length != VIRGL_SET_SAMPLE_MASK_SIZE)
959       return EINVAL;
960    mask = get_buf_entry(buf, VIRGL_SET_SAMPLE_MASK_MASK);
961    vrend_set_sample_mask(ctx, mask);
962    return 0;
963 }
964 
vrend_decode_set_min_samples(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)965 static int vrend_decode_set_min_samples(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
966 {
967    unsigned min_samples;
968 
969    if (length != VIRGL_SET_MIN_SAMPLES_SIZE)
970       return EINVAL;
971    min_samples = get_buf_entry(buf, VIRGL_SET_MIN_SAMPLES_MASK);
972    vrend_set_min_samples(ctx, min_samples);
973    return 0;
974 }
975 
vrend_decode_resource_copy_region(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)976 static int vrend_decode_resource_copy_region(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
977 {
978    struct pipe_box box;
979    uint32_t dst_handle, src_handle;
980    uint32_t dst_level, dstx, dsty, dstz;
981    uint32_t src_level;
982 
983    if (length != VIRGL_CMD_RESOURCE_COPY_REGION_SIZE)
984       return EINVAL;
985 
986    dst_handle = get_buf_entry(buf, VIRGL_CMD_RCR_DST_RES_HANDLE);
987    dst_level = get_buf_entry(buf, VIRGL_CMD_RCR_DST_LEVEL);
988    dstx = get_buf_entry(buf, VIRGL_CMD_RCR_DST_X);
989    dsty = get_buf_entry(buf, VIRGL_CMD_RCR_DST_Y);
990    dstz = get_buf_entry(buf, VIRGL_CMD_RCR_DST_Z);
991    src_handle = get_buf_entry(buf, VIRGL_CMD_RCR_SRC_RES_HANDLE);
992    src_level = get_buf_entry(buf, VIRGL_CMD_RCR_SRC_LEVEL);
993    box.x = get_buf_entry(buf, VIRGL_CMD_RCR_SRC_X);
994    box.y = get_buf_entry(buf, VIRGL_CMD_RCR_SRC_Y);
995    box.z = get_buf_entry(buf, VIRGL_CMD_RCR_SRC_Z);
996    box.width = get_buf_entry(buf, VIRGL_CMD_RCR_SRC_W);
997    box.height = get_buf_entry(buf, VIRGL_CMD_RCR_SRC_H);
998    box.depth = get_buf_entry(buf, VIRGL_CMD_RCR_SRC_D);
999 
1000    vrend_renderer_resource_copy_region(ctx, dst_handle,
1001                                        dst_level, dstx, dsty, dstz,
1002                                        src_handle, src_level,
1003                                        &box);
1004    return 0;
1005 }
1006 
1007 
vrend_decode_blit(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1008 static int vrend_decode_blit(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1009 {
1010    struct pipe_blit_info info;
1011    uint32_t dst_handle, src_handle, temp;
1012 
1013    if (length != VIRGL_CMD_BLIT_SIZE)
1014       return EINVAL;
1015    temp = get_buf_entry(buf, VIRGL_CMD_BLIT_S0);
1016    info.mask = temp & 0xff;
1017    info.filter = (temp >> 8) & 0x3;
1018    info.scissor_enable = (temp >> 10) & 0x1;
1019    info.render_condition_enable = (temp >> 11) & 0x1;
1020    info.alpha_blend = (temp >> 12) & 0x1;
1021    temp = get_buf_entry(buf, VIRGL_CMD_BLIT_SCISSOR_MINX_MINY);
1022    info.scissor.minx = temp & 0xffff;
1023    info.scissor.miny = (temp >> 16) & 0xffff;
1024    temp = get_buf_entry(buf, VIRGL_CMD_BLIT_SCISSOR_MAXX_MAXY);
1025    info.scissor.maxx = temp & 0xffff;
1026    info.scissor.maxy = (temp >> 16) & 0xffff;
1027    dst_handle = get_buf_entry(buf, VIRGL_CMD_BLIT_DST_RES_HANDLE);
1028    info.dst.level = get_buf_entry(buf, VIRGL_CMD_BLIT_DST_LEVEL);
1029    info.dst.format = get_buf_entry(buf, VIRGL_CMD_BLIT_DST_FORMAT);
1030    info.dst.box.x = get_buf_entry(buf, VIRGL_CMD_BLIT_DST_X);
1031    info.dst.box.y = get_buf_entry(buf, VIRGL_CMD_BLIT_DST_Y);
1032    info.dst.box.z = get_buf_entry(buf, VIRGL_CMD_BLIT_DST_Z);
1033    info.dst.box.width = get_buf_entry(buf, VIRGL_CMD_BLIT_DST_W);
1034    info.dst.box.height = get_buf_entry(buf, VIRGL_CMD_BLIT_DST_H);
1035    info.dst.box.depth = get_buf_entry(buf, VIRGL_CMD_BLIT_DST_D);
1036 
1037    src_handle = get_buf_entry(buf, VIRGL_CMD_BLIT_SRC_RES_HANDLE);
1038    info.src.level = get_buf_entry(buf, VIRGL_CMD_BLIT_SRC_LEVEL);
1039    info.src.format = get_buf_entry(buf, VIRGL_CMD_BLIT_SRC_FORMAT);
1040    info.src.box.x = get_buf_entry(buf, VIRGL_CMD_BLIT_SRC_X);
1041    info.src.box.y = get_buf_entry(buf, VIRGL_CMD_BLIT_SRC_Y);
1042    info.src.box.z = get_buf_entry(buf, VIRGL_CMD_BLIT_SRC_Z);
1043    info.src.box.width = get_buf_entry(buf, VIRGL_CMD_BLIT_SRC_W);
1044    info.src.box.height = get_buf_entry(buf, VIRGL_CMD_BLIT_SRC_H);
1045    info.src.box.depth = get_buf_entry(buf, VIRGL_CMD_BLIT_SRC_D);
1046 
1047    vrend_renderer_blit(ctx, dst_handle, src_handle, &info);
1048    return 0;
1049 }
1050 
vrend_decode_bind_sampler_states(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1051 static int vrend_decode_bind_sampler_states(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1052 {
1053    if (length < 2)
1054       return EINVAL;
1055 
1056    uint32_t shader_type = get_buf_entry(buf, VIRGL_BIND_SAMPLER_STATES_SHADER_TYPE);
1057    uint32_t start_slot = get_buf_entry(buf, VIRGL_BIND_SAMPLER_STATES_START_SLOT);
1058    uint32_t num_states = length - 2;
1059 
1060    if (shader_type >= PIPE_SHADER_TYPES)
1061       return EINVAL;
1062 
1063    vrend_bind_sampler_states(ctx, shader_type, start_slot, num_states,
1064                              get_buf_ptr(buf, VIRGL_BIND_SAMPLER_STATES_S0_HANDLE));
1065    return 0;
1066 }
1067 
vrend_decode_begin_query(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1068 static int vrend_decode_begin_query(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1069 {
1070    if (length != 1)
1071       return EINVAL;
1072 
1073    uint32_t handle = get_buf_entry(buf, VIRGL_QUERY_BEGIN_HANDLE);
1074 
1075    return vrend_begin_query(ctx, handle);
1076 }
1077 
vrend_decode_end_query(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1078 static int vrend_decode_end_query(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1079 {
1080    if (length != 1)
1081       return EINVAL;
1082 
1083    uint32_t handle = get_buf_entry(buf, VIRGL_QUERY_END_HANDLE);
1084 
1085    return vrend_end_query(ctx, handle);
1086 }
1087 
vrend_decode_get_query_result(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1088 static int vrend_decode_get_query_result(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1089 {
1090    if (length != 2)
1091       return EINVAL;
1092 
1093    uint32_t handle = get_buf_entry(buf, VIRGL_QUERY_RESULT_HANDLE);
1094    uint32_t wait = get_buf_entry(buf, VIRGL_QUERY_RESULT_WAIT);
1095 
1096    vrend_get_query_result(ctx, handle, wait);
1097    return 0;
1098 }
1099 
vrend_decode_get_query_result_qbo(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1100 static int vrend_decode_get_query_result_qbo(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1101 {
1102    if (length != VIRGL_QUERY_RESULT_QBO_SIZE)
1103       return EINVAL;
1104 
1105    uint32_t handle = get_buf_entry(buf, VIRGL_QUERY_RESULT_QBO_HANDLE);
1106    uint32_t qbo_handle = get_buf_entry(buf, VIRGL_QUERY_RESULT_QBO_QBO_HANDLE);
1107    uint32_t wait = get_buf_entry(buf, VIRGL_QUERY_RESULT_QBO_WAIT);
1108    uint32_t result_type = get_buf_entry(buf, VIRGL_QUERY_RESULT_QBO_RESULT_TYPE);
1109    uint32_t offset = get_buf_entry(buf, VIRGL_QUERY_RESULT_QBO_OFFSET);
1110    int32_t index = get_buf_entry(buf, VIRGL_QUERY_RESULT_QBO_INDEX);
1111 
1112    vrend_get_query_result_qbo(ctx, handle, qbo_handle, wait, result_type, offset, index);
1113    return 0;
1114 }
1115 
vrend_decode_set_render_condition(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1116 static int vrend_decode_set_render_condition(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1117 {
1118    if (length != VIRGL_RENDER_CONDITION_SIZE)
1119       return EINVAL;
1120 
1121    uint32_t handle = get_buf_entry(buf, VIRGL_RENDER_CONDITION_HANDLE);
1122    bool condition = get_buf_entry(buf, VIRGL_RENDER_CONDITION_CONDITION) & 1;
1123    uint mode = get_buf_entry(buf, VIRGL_RENDER_CONDITION_MODE);
1124 
1125    vrend_render_condition(ctx, handle, condition, mode);
1126    return 0;
1127 }
1128 
vrend_decode_set_sub_ctx(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1129 static int vrend_decode_set_sub_ctx(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1130 {
1131    if (length != 1)
1132       return EINVAL;
1133 
1134    uint32_t ctx_sub_id = get_buf_entry(buf, 1);
1135 
1136    vrend_renderer_set_sub_ctx(ctx, ctx_sub_id);
1137    return 0;
1138 }
1139 
vrend_decode_create_sub_ctx(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1140 static int vrend_decode_create_sub_ctx(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1141 {
1142    if (length != 1)
1143       return EINVAL;
1144 
1145    uint32_t ctx_sub_id = get_buf_entry(buf, 1);
1146 
1147    vrend_renderer_create_sub_ctx(ctx, ctx_sub_id);
1148    return 0;
1149 }
1150 
vrend_decode_destroy_sub_ctx(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1151 static int vrend_decode_destroy_sub_ctx(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1152 {
1153    if (length != 1)
1154       return EINVAL;
1155 
1156    uint32_t ctx_sub_id = get_buf_entry(buf, 1);
1157 
1158    vrend_renderer_destroy_sub_ctx(ctx, ctx_sub_id);
1159    return 0;
1160 }
1161 
vrend_decode_link_shader(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1162 static int vrend_decode_link_shader(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1163 {
1164    if (length != VIRGL_LINK_SHADER_SIZE)
1165       return EINVAL;
1166 
1167    uint32_t handles[PIPE_SHADER_TYPES];
1168    handles[PIPE_SHADER_VERTEX] = get_buf_entry(buf, VIRGL_LINK_SHADER_VERTEX_HANDLE);
1169    handles[PIPE_SHADER_FRAGMENT] = get_buf_entry(buf, VIRGL_LINK_SHADER_FRAGMENT_HANDLE);
1170    handles[PIPE_SHADER_GEOMETRY] = get_buf_entry(buf, VIRGL_LINK_SHADER_GEOMETRY_HANDLE);
1171    handles[PIPE_SHADER_TESS_CTRL] = get_buf_entry(buf, VIRGL_LINK_SHADER_TESS_CTRL_HANDLE);
1172    handles[PIPE_SHADER_TESS_EVAL] = get_buf_entry(buf, VIRGL_LINK_SHADER_TESS_EVAL_HANDLE);
1173    handles[PIPE_SHADER_COMPUTE] = get_buf_entry(buf, VIRGL_LINK_SHADER_COMPUTE_HANDLE);
1174 
1175    vrend_link_program_hook(ctx, handles);
1176    return 0;
1177 }
1178 
vrend_decode_bind_shader(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1179 static int vrend_decode_bind_shader(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1180 {
1181    uint32_t handle, type;
1182    if (length != VIRGL_BIND_SHADER_SIZE)
1183       return EINVAL;
1184 
1185    handle = get_buf_entry(buf, VIRGL_BIND_SHADER_HANDLE);
1186    type = get_buf_entry(buf, VIRGL_BIND_SHADER_TYPE);
1187 
1188    vrend_bind_shader(ctx, handle, type);
1189    return 0;
1190 }
1191 
vrend_decode_set_tess_state(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1192 static int vrend_decode_set_tess_state(struct vrend_context *ctx,
1193 				       const uint32_t *buf, uint32_t length)
1194 {
1195    float tess_factors[6];
1196    int i;
1197 
1198    if (length != VIRGL_TESS_STATE_SIZE)
1199       return EINVAL;
1200 
1201    for (i = 0; i < 6; i++) {
1202       tess_factors[i] = uif(get_buf_entry(buf, i + 1));
1203    }
1204    vrend_set_tess_state(ctx, tess_factors);
1205    return 0;
1206 }
1207 
vrend_decode_set_shader_buffers(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1208 static int vrend_decode_set_shader_buffers(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1209 {
1210    uint32_t num_ssbo;
1211    uint32_t shader_type, start_slot;
1212 
1213    if (length < 2)
1214       return EINVAL;
1215 
1216    num_ssbo = (length - 2) / VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE;
1217    shader_type = get_buf_entry(buf, VIRGL_SET_SHADER_BUFFER_SHADER_TYPE);
1218    start_slot = get_buf_entry(buf, VIRGL_SET_SHADER_BUFFER_START_SLOT);
1219    if (shader_type >= PIPE_SHADER_TYPES)
1220       return EINVAL;
1221 
1222    if (num_ssbo < 1)
1223       return 0;
1224 
1225    if (start_slot > PIPE_MAX_SHADER_BUFFERS ||
1226        num_ssbo > PIPE_MAX_SHADER_BUFFERS - start_slot)
1227       return EINVAL;
1228 
1229    for (uint32_t i = 0; i < num_ssbo; i++) {
1230       uint32_t offset = get_buf_entry(buf, VIRGL_SET_SHADER_BUFFER_OFFSET(i));
1231       uint32_t buf_len = get_buf_entry(buf, VIRGL_SET_SHADER_BUFFER_LENGTH(i));
1232       uint32_t handle = get_buf_entry(buf, VIRGL_SET_SHADER_BUFFER_RES_HANDLE(i));
1233       vrend_set_single_ssbo(ctx, shader_type, start_slot + i, offset, buf_len,
1234                             handle);
1235    }
1236    return 0;
1237 }
1238 
vrend_decode_set_atomic_buffers(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1239 static int vrend_decode_set_atomic_buffers(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1240 {
1241    uint32_t num_abo;
1242    uint32_t start_slot;
1243 
1244    if (length < 2)
1245       return EINVAL;
1246 
1247    num_abo = (length - 1) / VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE;
1248    start_slot = get_buf_entry(buf, VIRGL_SET_ATOMIC_BUFFER_START_SLOT);
1249    if (num_abo < 1)
1250       return 0;
1251 
1252    if (num_abo > PIPE_MAX_HW_ATOMIC_BUFFERS ||
1253        start_slot > PIPE_MAX_HW_ATOMIC_BUFFERS ||
1254        start_slot > PIPE_MAX_HW_ATOMIC_BUFFERS - num_abo)
1255       return EINVAL;
1256 
1257    for (uint32_t i = 0; i < num_abo; i++) {
1258       uint32_t offset = get_buf_entry(buf, i * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 2);
1259       uint32_t buf_len = get_buf_entry(buf, i * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 3);
1260       uint32_t handle = get_buf_entry(buf, i * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 4);
1261       vrend_set_single_abo(ctx, start_slot + i, offset, buf_len, handle);
1262    }
1263 
1264    return 0;
1265 }
1266 
vrend_decode_set_shader_images(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1267 static int vrend_decode_set_shader_images(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1268 {
1269    uint32_t num_images;
1270    uint32_t shader_type, start_slot;
1271    if (length < 2)
1272       return EINVAL;
1273 
1274    num_images = (length - 2) / VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE;
1275    shader_type = get_buf_entry(buf, VIRGL_SET_SHADER_IMAGE_SHADER_TYPE);
1276    start_slot = get_buf_entry(buf, VIRGL_SET_SHADER_IMAGE_START_SLOT);
1277    if (shader_type >= PIPE_SHADER_TYPES)
1278       return EINVAL;
1279 
1280    if (num_images < 1) {
1281       return 0;
1282    }
1283 
1284    if (start_slot > PIPE_MAX_SHADER_IMAGES ||
1285        start_slot + num_images > PIPE_MAX_SHADER_IMAGES)
1286       return EINVAL;
1287 
1288    for (uint32_t i = 0; i < num_images; i++) {
1289       uint32_t format = get_buf_entry(buf, VIRGL_SET_SHADER_IMAGE_FORMAT(i));
1290       uint32_t access = get_buf_entry(buf, VIRGL_SET_SHADER_IMAGE_ACCESS(i));
1291       uint32_t layer_offset = get_buf_entry(buf, VIRGL_SET_SHADER_IMAGE_LAYER_OFFSET(i));
1292       uint32_t level_size = get_buf_entry(buf, VIRGL_SET_SHADER_IMAGE_LEVEL_SIZE(i));
1293       uint32_t handle = get_buf_entry(buf, VIRGL_SET_SHADER_IMAGE_RES_HANDLE(i));
1294       vrend_set_single_image_view(ctx, shader_type, start_slot + i, format, access,
1295                                   layer_offset, level_size, handle);
1296    }
1297    return 0;
1298 }
1299 
vrend_decode_memory_barrier(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1300 static int vrend_decode_memory_barrier(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1301 {
1302    if (length != VIRGL_MEMORY_BARRIER_SIZE)
1303       return EINVAL;
1304 
1305    unsigned flags = get_buf_entry(buf, VIRGL_MEMORY_BARRIER_FLAGS);
1306    vrend_memory_barrier(ctx, flags);
1307    return 0;
1308 }
1309 
vrend_decode_launch_grid(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1310 static int vrend_decode_launch_grid(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1311 {
1312    uint32_t block[3], grid[3];
1313    uint32_t indirect_handle, indirect_offset;
1314    if (length != VIRGL_LAUNCH_GRID_SIZE)
1315       return EINVAL;
1316 
1317    block[0] = get_buf_entry(buf, VIRGL_LAUNCH_BLOCK_X);
1318    block[1] = get_buf_entry(buf, VIRGL_LAUNCH_BLOCK_Y);
1319    block[2] = get_buf_entry(buf, VIRGL_LAUNCH_BLOCK_Z);
1320    grid[0] = get_buf_entry(buf, VIRGL_LAUNCH_GRID_X);
1321    grid[1] = get_buf_entry(buf, VIRGL_LAUNCH_GRID_Y);
1322    grid[2] = get_buf_entry(buf, VIRGL_LAUNCH_GRID_Z);
1323    indirect_handle = get_buf_entry(buf, VIRGL_LAUNCH_INDIRECT_HANDLE);
1324    indirect_offset = get_buf_entry(buf, VIRGL_LAUNCH_INDIRECT_OFFSET);
1325    vrend_launch_grid(ctx, block, grid, indirect_handle, indirect_offset);
1326    return 0;
1327 }
1328 
vrend_decode_set_streamout_targets(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1329 static int vrend_decode_set_streamout_targets(struct vrend_context *ctx,
1330                                               const uint32_t *buf, uint32_t length)
1331 {
1332    uint32_t handles[16];
1333    uint32_t num_handles = length - 1;
1334    uint32_t append_bitmask;
1335    uint i;
1336 
1337    if (length < 1)
1338       return EINVAL;
1339    if (num_handles > ARRAY_SIZE(handles))
1340       return EINVAL;
1341 
1342    append_bitmask = get_buf_entry(buf, VIRGL_SET_STREAMOUT_TARGETS_APPEND_BITMASK);
1343    for (i = 0; i < num_handles; i++)
1344       handles[i] = get_buf_entry(buf, VIRGL_SET_STREAMOUT_TARGETS_H0 + i);
1345    vrend_set_streamout_targets(ctx, append_bitmask, num_handles, handles);
1346    return 0;
1347 }
1348 
vrend_decode_texture_barrier(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1349 static int vrend_decode_texture_barrier(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1350 {
1351    if (length != VIRGL_TEXTURE_BARRIER_SIZE)
1352       return EINVAL;
1353 
1354    unsigned flags = get_buf_entry(buf, VIRGL_TEXTURE_BARRIER_FLAGS);
1355    vrend_texture_barrier(ctx, flags);
1356    return 0;
1357 }
1358 
vrend_decode_set_debug_mask(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1359 static int vrend_decode_set_debug_mask(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1360 {
1361    char *flagstring;
1362    int slen = sizeof(uint32_t) * length;
1363 
1364    if (length < VIRGL_SET_DEBUG_FLAGS_MIN_SIZE)
1365       return EINVAL;
1366 
1367    const uint32_t *flag_buf = get_buf_ptr(buf, VIRGL_SET_DEBUG_FLAGSTRING_OFFSET);
1368    flagstring = malloc(slen+1);
1369 
1370    if (!flagstring) {
1371       return ENOMEM;
1372    }
1373 
1374    memcpy(flagstring, flag_buf, slen);
1375    flagstring[slen] = 0;
1376    vrend_context_set_debug_flags(ctx, flagstring);
1377 
1378    free(flagstring);
1379 
1380    return 0;
1381 }
1382 
vrend_decode_set_tweaks(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1383 static int vrend_decode_set_tweaks(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1384 {
1385    VREND_DEBUG(dbg_tweak, NULL, "Received TWEAK set command\n");
1386 
1387    if (length < VIRGL_SET_TWEAKS_SIZE)
1388       return EINVAL;
1389 
1390    uint32_t tweak_id = get_buf_entry(buf, VIRGL_SET_TWEAKS_ID);
1391    uint32_t tweak_value = get_buf_entry(buf, VIRGL_SET_TWEAKS_VALUE);
1392 
1393    vrend_set_active_tweaks(vrend_get_context_tweaks(ctx), tweak_id, tweak_value);
1394    return 0;
1395 }
1396 
1397 
vrend_decode_transfer3d(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1398 static int vrend_decode_transfer3d(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1399 {
1400    struct pipe_box box;
1401    uint32_t dst_handle;
1402    struct vrend_transfer_info info;
1403 
1404    if (length < VIRGL_TRANSFER3D_SIZE)
1405       return EINVAL;
1406 
1407    memset(&info, 0, sizeof(info));
1408    info.box = &box;
1409    vrend_decode_transfer_common(buf, &dst_handle, &info);
1410    info.offset = get_buf_entry(buf, VIRGL_TRANSFER3D_DATA_OFFSET);
1411    int transfer_mode = get_buf_entry(buf, VIRGL_TRANSFER3D_DIRECTION);
1412 
1413    if (transfer_mode != VIRGL_TRANSFER_TO_HOST &&
1414        transfer_mode != VIRGL_TRANSFER_FROM_HOST)
1415       return EINVAL;
1416 
1417    return vrend_renderer_transfer_iov(ctx, dst_handle, &info,
1418                                       transfer_mode);
1419 }
1420 
vrend_decode_copy_transfer3d(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1421 static int vrend_decode_copy_transfer3d(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1422 {
1423    struct pipe_box box;
1424    struct vrend_transfer_info info;
1425    uint32_t dst_handle;
1426    uint32_t src_handle;
1427 
1428    if (length != VIRGL_COPY_TRANSFER3D_SIZE)
1429       return EINVAL;
1430 
1431    memset(&info, 0, sizeof(info));
1432    info.box = &box;
1433 
1434    // synchronized is set either to 1 or 0. This means that we can use other bits
1435    // to identify the direction of copy transfer
1436    uint32_t flags = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_FLAGS);
1437    bool read_from_host = (flags & VIRGL_COPY_TRANSFER3D_FLAGS_READ_FROM_HOST) != 0;
1438    info.synchronized = (flags & VIRGL_COPY_TRANSFER3D_FLAGS_SYNCHRONIZED) != 0;
1439 
1440    if (!read_from_host) {
1441       // this means that guest would like to make transfer to host
1442       // it can also mean that guest is using legacy copy transfer path
1443       vrend_decode_transfer_common(buf, &dst_handle, &info);
1444       info.offset = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET);
1445       src_handle = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE);
1446 
1447       return vrend_renderer_copy_transfer3d(ctx, dst_handle, src_handle,
1448                                              &info);
1449    } else {
1450       vrend_decode_transfer_common(buf, &src_handle, &info);
1451       info.offset = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET);
1452       dst_handle = get_buf_entry(buf, VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE);
1453 
1454       return vrend_renderer_copy_transfer3d_from_host(ctx, dst_handle, src_handle,
1455                                                       &info);
1456    }
1457 }
1458 
vrend_decode_pipe_resource_create(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1459 static int vrend_decode_pipe_resource_create(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1460 {
1461    struct vrend_renderer_resource_create_args args = { 0 };
1462    uint32_t blob_id;
1463 
1464    if (length != VIRGL_PIPE_RES_CREATE_SIZE)
1465       return EINVAL;
1466 
1467    args.target = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_TARGET);
1468    args.format = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_FORMAT);
1469    args.bind = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_BIND);
1470    args.width = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_WIDTH);
1471    args.height = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_HEIGHT);
1472    args.depth = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_DEPTH);
1473    args.array_size = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_ARRAY_SIZE);
1474    args.last_level = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_LAST_LEVEL);
1475    args.nr_samples = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_NR_SAMPLES);
1476    args.flags = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_FLAGS);
1477    blob_id = get_buf_entry(buf, VIRGL_PIPE_RES_CREATE_BLOB_ID);
1478 
1479    return vrend_renderer_pipe_resource_create(ctx, blob_id, &args);
1480 }
1481 
vrend_decode_pipe_resource_set_type(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1482 static int vrend_decode_pipe_resource_set_type(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1483 {
1484    struct vrend_renderer_resource_set_type_args args = { 0 };
1485    uint32_t res_id;
1486 
1487    if (length >= VIRGL_PIPE_RES_SET_TYPE_SIZE(0))
1488       args.plane_count = (length - VIRGL_PIPE_RES_SET_TYPE_SIZE(0)) / 2;
1489 
1490    if (length != VIRGL_PIPE_RES_SET_TYPE_SIZE(args.plane_count) ||
1491        !args.plane_count || args.plane_count > VIRGL_GBM_MAX_PLANES)
1492       return EINVAL;
1493 
1494    res_id = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_RES_HANDLE);
1495    args.format = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_FORMAT);
1496    args.bind = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_BIND);
1497    args.width = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_WIDTH);
1498    args.height = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_HEIGHT);
1499    args.usage = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_USAGE);
1500    args.modifier = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_MODIFIER_LO);
1501    args.modifier |= (uint64_t)get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_MODIFIER_HI) << 32;
1502    for (uint32_t i = 0; i < args.plane_count; i++) {
1503       args.plane_strides[i] = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_PLANE_STRIDE(i));
1504       args.plane_offsets[i] = get_buf_entry(buf, VIRGL_PIPE_RES_SET_TYPE_PLANE_OFFSET(i));
1505    }
1506 
1507    return vrend_renderer_pipe_resource_set_type(ctx, res_id, &args);
1508 }
1509 
1510 static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,
1511                                        uint32_t ctx_id);
1512 
vrend_decode_ctx_fence_retire(uint64_t fence_id,void * retire_data)1513 static void vrend_decode_ctx_fence_retire(uint64_t fence_id,
1514                                           void *retire_data)
1515 {
1516    struct vrend_decode_ctx *dctx = retire_data;
1517    dctx->base.fence_retire(&dctx->base, 0, fence_id);
1518 }
1519 
vrend_renderer_context_create(uint32_t handle,uint32_t nlen,const char * debug_name)1520 struct virgl_context *vrend_renderer_context_create(uint32_t handle,
1521                                                     uint32_t nlen,
1522                                                     const char *debug_name)
1523 {
1524    struct vrend_decode_ctx *dctx;
1525 
1526    dctx = malloc(sizeof(struct vrend_decode_ctx));
1527    if (!dctx)
1528       return NULL;
1529 
1530    vrend_decode_ctx_init_base(dctx, handle);
1531 
1532    dctx->grctx = vrend_create_context(handle, nlen, debug_name);
1533    if (!dctx->grctx) {
1534       free(dctx);
1535       return NULL;
1536    }
1537 
1538    vrend_renderer_set_fence_retire(dctx->grctx,
1539                                    vrend_decode_ctx_fence_retire,
1540                                    dctx);
1541 
1542    return &dctx->base;
1543 }
1544 
vrend_decode_ctx_destroy(struct virgl_context * ctx)1545 static void vrend_decode_ctx_destroy(struct virgl_context *ctx)
1546 {
1547    TRACE_FUNC();
1548    struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
1549 
1550    vrend_destroy_context(dctx->grctx);
1551    free(dctx);
1552 }
1553 
vrend_decode_ctx_attach_resource(struct virgl_context * ctx,struct virgl_resource * res)1554 static void vrend_decode_ctx_attach_resource(struct virgl_context *ctx,
1555                                              struct virgl_resource *res)
1556 {
1557    TRACE_FUNC();
1558    struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
1559    vrend_renderer_attach_res_ctx(dctx->grctx, res);
1560 }
1561 
vrend_decode_ctx_detach_resource(struct virgl_context * ctx,struct virgl_resource * res)1562 static void vrend_decode_ctx_detach_resource(struct virgl_context *ctx,
1563                                              struct virgl_resource *res)
1564 {
1565    TRACE_FUNC();
1566    struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
1567    vrend_renderer_detach_res_ctx(dctx->grctx, res);
1568 }
1569 
vrend_decode_ctx_transfer_3d(struct virgl_context * ctx,struct virgl_resource * res,const struct vrend_transfer_info * info,int transfer_mode)1570 static int vrend_decode_ctx_transfer_3d(struct virgl_context *ctx,
1571                                         struct virgl_resource *res,
1572                                         const struct vrend_transfer_info *info,
1573                                         int transfer_mode)
1574 {
1575    TRACE_FUNC();
1576    struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
1577    int ret = vrend_renderer_transfer_iov(dctx->grctx, res->res_id, info,
1578                                          transfer_mode);
1579    return vrend_check_no_error(dctx->grctx) || ret ? ret : EINVAL;
1580 }
1581 
vrend_decode_ctx_get_blob(struct virgl_context * ctx,UNUSED uint32_t res_id,uint64_t blob_id,UNUSED uint64_t blob_size,UNUSED uint32_t blob_flags,struct virgl_context_blob * blob)1582 static int vrend_decode_ctx_get_blob(struct virgl_context *ctx,
1583                                      UNUSED uint32_t res_id,
1584                                      uint64_t blob_id,
1585                                      UNUSED uint64_t blob_size,
1586                                      UNUSED uint32_t blob_flags,
1587                                      struct virgl_context_blob *blob)
1588 {
1589    TRACE_FUNC();
1590    struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
1591 
1592    blob->type = VIRGL_RESOURCE_FD_INVALID;
1593    /* this transfers ownership and blob_id is no longer valid */
1594    blob->u.pipe_resource = vrend_get_blob_pipe(dctx->grctx, blob_id);
1595    if (!blob->u.pipe_resource)
1596       return -EINVAL;
1597 
1598    blob->map_info = vrend_renderer_resource_get_map_info(blob->u.pipe_resource);
1599    return 0;
1600 }
1601 
vrend_decode_get_memory_info(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1602 static int vrend_decode_get_memory_info(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1603 {
1604    TRACE_FUNC();
1605    if (length != 1)
1606       return EINVAL;
1607 
1608    uint32_t res_handle = get_buf_entry(buf, 1);
1609 
1610    vrend_renderer_get_meminfo(ctx, res_handle);
1611 
1612    return 0;
1613 }
1614 
vrend_decode_send_string_marker(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1615 static int vrend_decode_send_string_marker(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1616 {
1617    uint32_t buf_len = sizeof(uint32_t) * (length - 1);
1618 
1619    if (length < VIRGL_SEND_STRING_MARKER_MIN_SIZE) {
1620       fprintf(stderr, "minimal command length not okay\n");
1621       return EINVAL;
1622    }
1623 
1624    uint32_t str_len = get_buf_entry(buf, VIRGL_SEND_STRING_MARKER_STRING_SIZE);
1625    if (str_len > buf_len) {
1626        fprintf(stderr, "String len %u > buf_len %u\n", str_len, buf_len);
1627        return EINVAL;
1628    }
1629 
1630    vrend_context_emit_string_marker(ctx, str_len, get_buf_ptr(buf, VIRGL_SEND_STRING_MARKER_OFFSET));
1631 
1632    return 0;
1633 }
1634 
1635 #ifdef ENABLE_VIDEO
1636 /* video codec related functions */
1637 
vrend_decode_create_video_codec(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1638 static int vrend_decode_create_video_codec(struct vrend_context *ctx,
1639                                            const uint32_t *buf,
1640                                            uint32_t length)
1641 {
1642    struct vrend_video_context *vctx = vrend_context_get_video_ctx(ctx);
1643 
1644    if (length < VIRGL_CREATE_VIDEO_CODEC_MIN_SIZE)
1645       return EINVAL;
1646 
1647    uint32_t handle     = get_buf_entry(buf, VIRGL_CREATE_VIDEO_CODEC_HANDLE);
1648    uint32_t profile    = get_buf_entry(buf, VIRGL_CREATE_VIDEO_CODEC_PROFILE);
1649    uint32_t entrypoint = get_buf_entry(buf, VIRGL_CREATE_VIDEO_CODEC_ENTRYPOINT);
1650    uint32_t chroma_fmt = get_buf_entry(buf, VIRGL_CREATE_VIDEO_CODEC_CHROMA_FMT);
1651    uint32_t level      = get_buf_entry(buf, VIRGL_CREATE_VIDEO_CODEC_LEVEL);
1652    uint32_t width      = get_buf_entry(buf, VIRGL_CREATE_VIDEO_CODEC_WIDTH);
1653    uint32_t height     = get_buf_entry(buf, VIRGL_CREATE_VIDEO_CODEC_HEIGHT);
1654    uint32_t max_ref    = 2; /* The max number of ref frames is 2 by default */
1655 
1656    if (length >= VIRGL_CREATE_VIDEO_CODEC_MAX_REF)
1657       max_ref = get_buf_entry(buf, VIRGL_CREATE_VIDEO_CODEC_MAX_REF);
1658 
1659    vrend_video_create_codec(vctx, handle, profile, entrypoint,
1660                             chroma_fmt, level, width, height, max_ref, 0);
1661 
1662    return 0;
1663 }
1664 
vrend_decode_destroy_video_codec(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1665 static int vrend_decode_destroy_video_codec(struct vrend_context *ctx,
1666                                             const uint32_t *buf,
1667                                             uint32_t length)
1668 {
1669    struct vrend_video_context *vctx = vrend_context_get_video_ctx(ctx);
1670 
1671     if (length < VIRGL_DESTROY_VIDEO_CODEC_MIN_SIZE)
1672        return EINVAL;
1673 
1674    uint32_t handle = get_buf_entry(buf, VIRGL_DESTROY_VIDEO_CODEC_HANDLE);
1675    vrend_video_destroy_codec(vctx, handle);
1676 
1677    return 0;
1678 }
1679 
vrend_decode_create_video_buffer(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1680 static int vrend_decode_create_video_buffer(struct vrend_context *ctx,
1681                                             const uint32_t *buf,
1682                                             uint32_t length)
1683 {
1684    uint32_t i, num_res;
1685    uint32_t res_handles[VREND_VIDEO_BUFFER_PLANE_NUM];
1686    struct vrend_video_context *vctx = vrend_context_get_video_ctx(ctx);
1687 
1688    if (length < VIRGL_CREATE_VIDEO_BUFFER_MIN_SIZE)
1689       return EINVAL;
1690 
1691    num_res = length - VIRGL_CREATE_VIDEO_BUFFER_RES_BASE + 1;
1692    if (num_res > VREND_VIDEO_BUFFER_PLANE_NUM)
1693        num_res = VREND_VIDEO_BUFFER_PLANE_NUM;
1694 
1695    uint32_t handle = get_buf_entry(buf, VIRGL_CREATE_VIDEO_BUFFER_HANDLE);
1696    uint32_t format = get_buf_entry(buf, VIRGL_CREATE_VIDEO_BUFFER_FORMAT);
1697    uint32_t width  = get_buf_entry(buf, VIRGL_CREATE_VIDEO_BUFFER_WIDTH);
1698    uint32_t height = get_buf_entry(buf, VIRGL_CREATE_VIDEO_BUFFER_HEIGHT);
1699 
1700    memset(res_handles, 0, sizeof(res_handles));
1701    for (i = 0; i < num_res; i++)
1702        res_handles[i] = get_buf_entry(buf,
1703                                       VIRGL_CREATE_VIDEO_BUFFER_RES_BASE + i);
1704 
1705    vrend_video_create_buffer(vctx, handle, format, width, height,
1706                                       res_handles, num_res);
1707 
1708    return 0;
1709 }
1710 
vrend_decode_destroy_video_buffer(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1711 static int vrend_decode_destroy_video_buffer(struct vrend_context *ctx,
1712                                              const uint32_t *buf,
1713                                              uint32_t length)
1714 {
1715    struct vrend_video_context *vctx = vrend_context_get_video_ctx(ctx);
1716 
1717    if (length < VIRGL_DESTROY_VIDEO_BUFFER_MIN_SIZE)
1718       return EINVAL;
1719 
1720    uint32_t handle = get_buf_entry(buf, VIRGL_DESTROY_VIDEO_BUFFER_HANDLE);
1721    vrend_video_destroy_buffer(vctx, handle);
1722 
1723    return 0;
1724 }
1725 
vrend_decode_begin_frame(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1726 static int vrend_decode_begin_frame(struct vrend_context *ctx,
1727                                     const uint32_t *buf,
1728                                     uint32_t length)
1729 {
1730    struct vrend_video_context *vctx = vrend_context_get_video_ctx(ctx);
1731 
1732    if (length < VIRGL_BEGIN_FRAME_MIN_SIZE)
1733       return EINVAL;
1734 
1735    uint32_t cdc_handle = get_buf_entry(buf, VIRGL_BEGIN_FRAME_CDC_HANDLE);
1736    uint32_t tgt_handle = get_buf_entry(buf, VIRGL_BEGIN_FRAME_TGT_HANDLE);
1737    vrend_video_begin_frame(vctx, cdc_handle, tgt_handle);
1738 
1739    return 0;
1740 }
1741 
vrend_decode_decode_bitstream(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1742 static int vrend_decode_decode_bitstream(struct vrend_context *ctx,
1743                                          const uint32_t *buf,
1744                                          uint32_t length)
1745 {
1746    struct vrend_video_context *vctx = vrend_context_get_video_ctx(ctx);
1747 
1748    if (length < VIRGL_DECODE_BS_MIN_SIZE)
1749       return EINVAL;
1750 
1751    uint32_t cdc_handle = get_buf_entry(buf, VIRGL_DECODE_BS_CDC_HANDLE);
1752    uint32_t tgt_handle = get_buf_entry(buf, VIRGL_DECODE_BS_TGT_HANDLE);
1753    uint32_t dsc_handle = get_buf_entry(buf, VIRGL_DECODE_BS_DSC_HANDLE);
1754    uint32_t buf_handle = get_buf_entry(buf, VIRGL_DECODE_BS_BUF_HANDLE);
1755    uint32_t buf_size   = get_buf_entry(buf, VIRGL_DECODE_BS_BUF_SIZE);
1756 
1757    vrend_video_decode_bitstream(vctx, cdc_handle, tgt_handle,
1758                                 dsc_handle, 1, &buf_handle, &buf_size);
1759 
1760    return 0;
1761 }
1762 
vrend_decode_encode_bitstream(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1763 static int vrend_decode_encode_bitstream(struct vrend_context *ctx,
1764                                          const uint32_t *buf,
1765                                          uint32_t length)
1766 {
1767    struct vrend_video_context *vctx = vrend_context_get_video_ctx(ctx);
1768 
1769    if (length < VIRGL_ENCODE_BS_MIN_SIZE)
1770       return EINVAL;
1771 
1772    uint32_t cdc_handle  = get_buf_entry(buf, VIRGL_ENCODE_BS_CDC_HANDLE);
1773    uint32_t src_handle  = get_buf_entry(buf, VIRGL_ENCODE_BS_SRC_HANDLE);
1774    uint32_t dest_handle = get_buf_entry(buf, VIRGL_ENCODE_BS_DEST_HANDLE);
1775    uint32_t desc_handle = get_buf_entry(buf, VIRGL_ENCODE_BS_DESC_HANDLE);
1776    uint32_t feed_handle = get_buf_entry(buf, VIRGL_ENCODE_BS_FEED_HANDLE);
1777 
1778    vrend_video_encode_bitstream(vctx, cdc_handle, src_handle, dest_handle,
1779                                 desc_handle, feed_handle);
1780 
1781    return 0;
1782 }
1783 
vrend_decode_end_frame(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1784 static int vrend_decode_end_frame(struct vrend_context *ctx,
1785                                   const uint32_t *buf,
1786                                   uint32_t length)
1787 {
1788    struct vrend_video_context *vctx = vrend_context_get_video_ctx(ctx);
1789 
1790    if (length < VIRGL_END_FRAME_MIN_SIZE)
1791       return EINVAL;
1792 
1793    uint32_t cdc_handle = get_buf_entry(buf, VIRGL_END_FRAME_CDC_HANDLE);
1794    uint32_t tgt_handle = get_buf_entry(buf, VIRGL_END_FRAME_TGT_HANDLE);
1795 
1796    vrend_video_end_frame(vctx, cdc_handle, tgt_handle);
1797 
1798    return 0;
1799 }
1800 
1801 #else
1802 
vrend_unsupported(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1803 static int vrend_unsupported(struct vrend_context *ctx,
1804                                     const uint32_t *buf,
1805                                     uint32_t length)
1806 {
1807    (void)ctx;
1808    (void)buf;
1809    (void)length;
1810    return EINVAL;
1811 }
1812 
1813 #endif /* ENABLE_VIDEO */
1814 
1815 
1816 typedef int (*vrend_decode_callback)(struct vrend_context *ctx, const uint32_t *buf, uint32_t length);
1817 
vrend_decode_dummy(struct vrend_context * ctx,const uint32_t * buf,uint32_t length)1818 static int vrend_decode_dummy(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
1819 {
1820    (void)ctx;
1821    (void)buf;
1822    (void)length;
1823    return 0;
1824 }
1825 
1826 static const vrend_decode_callback decode_table[VIRGL_MAX_COMMANDS] = {
1827    [VIRGL_CCMD_NOP] = vrend_decode_dummy,
1828    [VIRGL_CCMD_CREATE_OBJECT] = vrend_decode_create_object,
1829    [VIRGL_CCMD_BIND_OBJECT] = vrend_decode_bind_object,
1830    [VIRGL_CCMD_DESTROY_OBJECT] = vrend_decode_destroy_object,
1831    [VIRGL_CCMD_CLEAR] = vrend_decode_clear,
1832    [VIRGL_CCMD_CLEAR_TEXTURE] = vrend_decode_clear_texture,
1833    [VIRGL_CCMD_DRAW_VBO] = vrend_decode_draw_vbo,
1834    [VIRGL_CCMD_SET_FRAMEBUFFER_STATE] = vrend_decode_set_framebuffer_state,
1835    [VIRGL_CCMD_SET_VERTEX_BUFFERS] = vrend_decode_set_vertex_buffers,
1836    [VIRGL_CCMD_RESOURCE_INLINE_WRITE] = vrend_decode_resource_inline_write,
1837    [VIRGL_CCMD_SET_VIEWPORT_STATE] = vrend_decode_set_viewport_state,
1838    [VIRGL_CCMD_SET_SAMPLER_VIEWS] = vrend_decode_set_sampler_views,
1839    [VIRGL_CCMD_SET_INDEX_BUFFER] = vrend_decode_set_index_buffer,
1840    [VIRGL_CCMD_SET_CONSTANT_BUFFER] = vrend_decode_set_constant_buffer,
1841    [VIRGL_CCMD_SET_STENCIL_REF] = vrend_decode_set_stencil_ref,
1842    [VIRGL_CCMD_SET_BLEND_COLOR] = vrend_decode_set_blend_color,
1843    [VIRGL_CCMD_SET_SCISSOR_STATE] = vrend_decode_set_scissor_state,
1844    [VIRGL_CCMD_BLIT] = vrend_decode_blit,
1845    [VIRGL_CCMD_RESOURCE_COPY_REGION] = vrend_decode_resource_copy_region,
1846    [VIRGL_CCMD_BIND_SAMPLER_STATES] = vrend_decode_bind_sampler_states,
1847    [VIRGL_CCMD_BEGIN_QUERY] = vrend_decode_begin_query,
1848    [VIRGL_CCMD_END_QUERY] = vrend_decode_end_query,
1849    [VIRGL_CCMD_GET_QUERY_RESULT] = vrend_decode_get_query_result,
1850    [VIRGL_CCMD_SET_POLYGON_STIPPLE] = vrend_decode_set_polygon_stipple,
1851    [VIRGL_CCMD_SET_CLIP_STATE] = vrend_decode_set_clip_state,
1852    [VIRGL_CCMD_SET_SAMPLE_MASK] = vrend_decode_set_sample_mask,
1853    [VIRGL_CCMD_SET_MIN_SAMPLES] = vrend_decode_set_min_samples,
1854    [VIRGL_CCMD_SET_STREAMOUT_TARGETS] = vrend_decode_set_streamout_targets,
1855    [VIRGL_CCMD_SET_RENDER_CONDITION] = vrend_decode_set_render_condition,
1856    [VIRGL_CCMD_SET_UNIFORM_BUFFER] = vrend_decode_set_uniform_buffer,
1857    [VIRGL_CCMD_SET_SUB_CTX] = vrend_decode_set_sub_ctx,
1858    [VIRGL_CCMD_CREATE_SUB_CTX] = vrend_decode_create_sub_ctx,
1859    [VIRGL_CCMD_DESTROY_SUB_CTX] = vrend_decode_destroy_sub_ctx,
1860    [VIRGL_CCMD_BIND_SHADER] = vrend_decode_bind_shader,
1861    [VIRGL_CCMD_SET_TESS_STATE] = vrend_decode_set_tess_state,
1862    [VIRGL_CCMD_SET_SHADER_BUFFERS] = vrend_decode_set_shader_buffers,
1863    [VIRGL_CCMD_SET_SHADER_IMAGES] = vrend_decode_set_shader_images,
1864    [VIRGL_CCMD_SET_ATOMIC_BUFFERS] = vrend_decode_set_atomic_buffers,
1865    [VIRGL_CCMD_MEMORY_BARRIER] = vrend_decode_memory_barrier,
1866    [VIRGL_CCMD_LAUNCH_GRID] = vrend_decode_launch_grid,
1867    [VIRGL_CCMD_SET_FRAMEBUFFER_STATE_NO_ATTACH] = vrend_decode_set_framebuffer_state_no_attach,
1868    [VIRGL_CCMD_TEXTURE_BARRIER] = vrend_decode_texture_barrier,
1869    [VIRGL_CCMD_SET_DEBUG_FLAGS] = vrend_decode_set_debug_mask,
1870    [VIRGL_CCMD_GET_QUERY_RESULT_QBO] = vrend_decode_get_query_result_qbo,
1871    [VIRGL_CCMD_TRANSFER3D] = vrend_decode_transfer3d,
1872    [VIRGL_CCMD_COPY_TRANSFER3D] = vrend_decode_copy_transfer3d,
1873    [VIRGL_CCMD_END_TRANSFERS] = vrend_decode_dummy,
1874    [VIRGL_CCMD_SET_TWEAKS] = vrend_decode_set_tweaks,
1875    [VIRGL_CCMD_PIPE_RESOURCE_CREATE] = vrend_decode_pipe_resource_create,
1876    [VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE] = vrend_decode_pipe_resource_set_type,
1877    [VIRGL_CCMD_GET_MEMORY_INFO] = vrend_decode_get_memory_info,
1878    [VIRGL_CCMD_SEND_STRING_MARKER] = vrend_decode_send_string_marker,
1879    [VIRGL_CCMD_LINK_SHADER] = vrend_decode_link_shader,
1880 #ifdef ENABLE_VIDEO
1881    [VIRGL_CCMD_CREATE_VIDEO_CODEC] = vrend_decode_create_video_codec,
1882    [VIRGL_CCMD_DESTROY_VIDEO_CODEC] = vrend_decode_destroy_video_codec,
1883    [VIRGL_CCMD_CREATE_VIDEO_BUFFER] = vrend_decode_create_video_buffer,
1884    [VIRGL_CCMD_DESTROY_VIDEO_BUFFER] = vrend_decode_destroy_video_buffer,
1885    [VIRGL_CCMD_BEGIN_FRAME] = vrend_decode_begin_frame,
1886    [VIRGL_CCMD_DECODE_MACROBLOCK] = vrend_decode_dummy,
1887    [VIRGL_CCMD_DECODE_BITSTREAM] = vrend_decode_decode_bitstream,
1888    [VIRGL_CCMD_ENCODE_BITSTREAM] = vrend_decode_encode_bitstream,
1889    [VIRGL_CCMD_END_FRAME] = vrend_decode_end_frame,
1890 #else
1891    [VIRGL_CCMD_CREATE_VIDEO_CODEC] = vrend_unsupported,
1892    [VIRGL_CCMD_DESTROY_VIDEO_CODEC] = vrend_unsupported,
1893    [VIRGL_CCMD_CREATE_VIDEO_BUFFER] = vrend_unsupported,
1894    [VIRGL_CCMD_DESTROY_VIDEO_BUFFER] = vrend_unsupported,
1895    [VIRGL_CCMD_BEGIN_FRAME] = vrend_unsupported,
1896    [VIRGL_CCMD_DECODE_MACROBLOCK] = vrend_unsupported,
1897    [VIRGL_CCMD_DECODE_BITSTREAM] = vrend_unsupported,
1898    [VIRGL_CCMD_ENCODE_BITSTREAM] = vrend_unsupported,
1899    [VIRGL_CCMD_END_FRAME] = vrend_unsupported,
1900 #endif
1901 };
1902 
vrend_decode_ctx_submit_cmd(struct virgl_context * ctx,const void * buffer,size_t size)1903 static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx,
1904                                        const void *buffer,
1905                                        size_t size)
1906 {
1907    TRACE_FUNC();
1908    struct vrend_decode_ctx *gdctx = (struct vrend_decode_ctx *)ctx;
1909    bool bret;
1910    int ret;
1911 
1912    bret = vrend_hw_switch_context(gdctx->grctx, true);
1913    if (bret == false)
1914       return EINVAL;
1915 
1916    const uint32_t *typed_buf = (const uint32_t *)buffer;
1917    const uint32_t buf_total = (uint32_t)(size / sizeof(uint32_t));
1918    uint32_t buf_offset = 0;
1919 
1920    while (buf_offset < buf_total) {
1921       const uint32_t cur_offset = buf_offset;
1922       const uint32_t *buf = &typed_buf[buf_offset];
1923       uint32_t len = *buf >> 16;
1924       uint32_t cmd = *buf & 0xff;
1925 
1926       if (cmd >= VIRGL_MAX_COMMANDS)
1927          return EINVAL;
1928 
1929       buf_offset += len + 1;
1930 
1931       ret = 0;
1932       /* check if the guest is doing something bad */
1933       if (buf_offset > buf_total) {
1934          vrend_report_buffer_error(gdctx->grctx, 0);
1935          break;
1936       }
1937 
1938       VREND_DEBUG(dbg_cmd, gdctx->grctx, "%-4d %-20s len:%d\n",
1939                   cur_offset, vrend_get_comand_name(cmd), len);
1940 
1941       TRACE_SCOPE_SLOW(vrend_get_comand_name(cmd));
1942 
1943       ret = decode_table[cmd](gdctx->grctx, buf, len);
1944       if (!vrend_check_no_error(gdctx->grctx) && !ret)
1945          ret = EINVAL;
1946       if (ret) {
1947          vrend_printf("context %d failed to dispatch %s: %d\n",
1948                gdctx->base.ctx_id, vrend_get_comand_name(cmd), ret);
1949          if (ret == EINVAL)
1950             vrend_report_buffer_error(gdctx->grctx, *buf);
1951          return ret;
1952       }
1953    }
1954    return 0;
1955 }
1956 
vrend_decode_ctx_get_fencing_fd(UNUSED struct virgl_context * ctx)1957 static int vrend_decode_ctx_get_fencing_fd(UNUSED struct virgl_context *ctx)
1958 {
1959    return vrend_renderer_get_poll_fd();
1960 }
1961 
vrend_decode_ctx_retire_fences(UNUSED struct virgl_context * ctx)1962 static void vrend_decode_ctx_retire_fences(UNUSED struct virgl_context *ctx)
1963 {
1964    vrend_renderer_check_fences();
1965 }
1966 
vrend_decode_ctx_submit_fence(struct virgl_context * ctx,uint32_t flags,uint32_t ring_idx,uint64_t fence_id)1967 static int vrend_decode_ctx_submit_fence(struct virgl_context *ctx,
1968                                          uint32_t flags,
1969                                          uint32_t ring_idx,
1970                                          uint64_t fence_id)
1971 {
1972    struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx;
1973 
1974    if (ring_idx)
1975       return -EINVAL;
1976 
1977    return vrend_renderer_create_fence(dctx->grctx, flags, fence_id);
1978 }
1979 
vrend_decode_ctx_init_base(struct vrend_decode_ctx * dctx,uint32_t ctx_id)1980 static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,
1981                                        uint32_t ctx_id)
1982 {
1983    struct virgl_context *ctx = &dctx->base ;
1984 
1985    for (unsigned i = 0; i < VIRGL_MAX_COMMANDS; ++i)
1986       assert(decode_table[i]);
1987 
1988    ctx->ctx_id = ctx_id;
1989    ctx->destroy = vrend_decode_ctx_destroy;
1990    ctx->attach_resource = vrend_decode_ctx_attach_resource;
1991    ctx->detach_resource = vrend_decode_ctx_detach_resource;
1992    ctx->transfer_3d = vrend_decode_ctx_transfer_3d;
1993    ctx->get_blob = vrend_decode_ctx_get_blob;
1994    ctx->submit_cmd = vrend_decode_ctx_submit_cmd;
1995 
1996    ctx->get_fencing_fd = vrend_decode_ctx_get_fencing_fd;
1997    ctx->retire_fences = vrend_decode_ctx_retire_fences;
1998    ctx->submit_fence = vrend_decode_ctx_submit_fence;
1999 }
2000