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