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 #ifdef HAVE_CONFIG_H 25 #include "config.h" 26 #endif 27 28 #include <unistd.h> 29 #include <stdio.h> 30 #include <errno.h> 31 #include "pipe/p_shader_tokens.h" 32 33 #include "pipe/p_context.h" 34 #include "pipe/p_defines.h" 35 #include "pipe/p_screen.h" 36 #include "pipe/p_state.h" 37 #include "util/u_inlines.h" 38 #include "util/u_memory.h" 39 #include "util/u_dual_blend.h" 40 41 #include "os/os_thread.h" 42 #include "util/u_double_list.h" 43 #include "util/u_format.h" 44 #include "tgsi/tgsi_parse.h" 45 46 #include "vrend_object.h" 47 #include "vrend_shader.h" 48 49 #include "vrend_renderer.h" 50 51 #include "virgl_hw.h" 52 53 #include "tgsi/tgsi_text.h" 54 55 #ifdef HAVE_EVENTFD 56 #include <sys/eventfd.h> 57 #endif 58 59 /* debugging aid to dump shaders */ 60 int vrend_dump_shaders; 61 62 /* debugging via KHR_debug extension */ 63 int vrend_use_debug_cb = 0; 64 65 struct vrend_if_cbs *vrend_clicbs; 66 67 struct vrend_fence { 68 uint32_t fence_id; 69 uint32_t ctx_id; 70 GLsync syncobj; 71 struct list_head fences; 72 }; 73 74 struct vrend_query { 75 struct list_head waiting_queries; 76 77 GLuint id; 78 GLuint type; 79 GLuint index; 80 GLuint gltype; 81 int ctx_id; 82 struct vrend_resource *res; 83 uint64_t current_total; 84 }; 85 86 struct global_error_state { 87 enum virgl_errors last_error; 88 }; 89 90 enum features_id 91 { 92 feat_arb_or_gles_ext_texture_buffer, 93 feat_arb_robustness, 94 feat_base_instance, 95 feat_barrier, 96 feat_bit_encoding, 97 feat_compute_shader, 98 feat_copy_image, 99 feat_conditional_render_inverted, 100 feat_cube_map_array, 101 feat_debug_cb, 102 feat_draw_instance, 103 feat_dual_src_blend, 104 feat_fb_no_attach, 105 feat_framebuffer_fetch, 106 feat_geometry_shader, 107 feat_gl_conditional_render, 108 feat_gl_prim_restart, 109 feat_gles_khr_robustness, 110 feat_gles31_vertex_attrib_binding, 111 feat_images, 112 feat_indep_blend, 113 feat_indep_blend_func, 114 feat_indirect_draw, 115 feat_mesa_invert, 116 feat_ms_scaled_blit, 117 feat_multisample, 118 feat_nv_conditional_render, 119 feat_nv_prim_restart, 120 feat_polygon_offset_clamp, 121 feat_robust_buffer_access, 122 feat_sample_mask, 123 feat_sample_shading, 124 feat_samplers, 125 feat_shader_clock, 126 feat_ssbo, 127 feat_ssbo_barrier, 128 feat_stencil_texturing, 129 feat_storage_multisample, 130 feat_tessellation, 131 feat_texture_array, 132 feat_texture_barrier, 133 feat_texture_buffer_range, 134 feat_texture_gather, 135 feat_texture_multisample, 136 feat_texture_srgb_decode, 137 feat_texture_storage, 138 feat_texture_view, 139 feat_transform_feedback, 140 feat_transform_feedback2, 141 feat_transform_feedback3, 142 feat_transform_feedback_overflow_query, 143 feat_txqs, 144 feat_ubo, 145 feat_viewport_array, 146 feat_last, 147 }; 148 149 #define FEAT_MAX_EXTS 4 150 #define UNAVAIL INT_MAX 151 152 static const struct { 153 int gl_ver; 154 int gles_ver; 155 const char *gl_ext[FEAT_MAX_EXTS]; 156 } feature_list[] = { 157 [feat_arb_or_gles_ext_texture_buffer] = { 31, UNAVAIL, { "GL_ARB_texture_buffer_object", "GL_EXT_texture_buffer", NULL } }, 158 [feat_arb_robustness] = { UNAVAIL, UNAVAIL, { "GL_ARB_robustness" } }, 159 [feat_base_instance] = { 42, UNAVAIL, { "GL_ARB_base_instance", "GL_EXT_base_instance" } }, 160 [feat_barrier] = { 42, 31, {} }, 161 [feat_bit_encoding] = { 33, UNAVAIL, { "GL_ARB_shader_bit_encoding" } }, 162 [feat_compute_shader] = { 43, 31, { "GL_ARB_compute_shader" } }, 163 [feat_copy_image] = { 43, 32, { "GL_ARB_copy_image", "GL_EXT_copy_image", "GL_OES_copy_image" } }, 164 [feat_conditional_render_inverted] = { 45, UNAVAIL, { "GL_ARB_conditional_render_inverted" } }, 165 [feat_cube_map_array] = { 40, UNAVAIL, { "GL_ARB_texture_cube_map_array", "GL_EXT_texture_cube_map_array", "GL_OES_texture_cube_map_array" } }, 166 [feat_debug_cb] = { UNAVAIL, UNAVAIL, {} }, /* special case */ 167 [feat_draw_instance] = { 31, 30, { "GL_ARB_draw_instanced" } }, 168 [feat_dual_src_blend] = { 33, UNAVAIL, { "GL_ARB_blend_func_extended" } }, 169 [feat_fb_no_attach] = { 43, 31, { "GL_ARB_framebuffer_no_attachments" } }, 170 [feat_framebuffer_fetch] = { UNAVAIL, UNAVAIL, { "GL_EXT_shader_framebuffer_fetch" } }, 171 [feat_geometry_shader] = { 32, 32, {"GL_EXT_geometry_shader", "GL_OES_geometry_shader"} }, 172 [feat_gl_conditional_render] = { 30, UNAVAIL, {} }, 173 [feat_gl_prim_restart] = { 31, 30, {} }, 174 [feat_gles_khr_robustness] = { UNAVAIL, UNAVAIL, { "GL_KHR_robustness" } }, 175 [feat_gles31_vertex_attrib_binding] = { 43, 31, { "GL_ARB_vertex_attrib_binding" } }, 176 [feat_images] = { 42, 31, { "GL_ARB_shader_image_load_store" } }, 177 [feat_indep_blend] = { 30, UNAVAIL, { "GL_EXT_draw_buffers2" } }, 178 [feat_indep_blend_func] = { 40, UNAVAIL, { "GL_ARB_draw_buffers_blend" } }, 179 [feat_indirect_draw] = { 40, 31, { "GL_ARB_draw_indirect" } }, 180 [feat_mesa_invert] = { UNAVAIL, UNAVAIL, { "GL_MESA_pack_invert" } }, 181 [feat_ms_scaled_blit] = { UNAVAIL, UNAVAIL, { "GL_EXT_framebuffer_multisample_blit_scaled" } }, 182 [feat_multisample] = { 32, 30, { "GL_ARB_texture_multisample" } }, 183 [feat_nv_conditional_render] = { UNAVAIL, UNAVAIL, { "GL_NV_conditional_render" } }, 184 [feat_nv_prim_restart] = { UNAVAIL, UNAVAIL, { "GL_NV_primitive_restart" } }, 185 [feat_polygon_offset_clamp] = { 46, UNAVAIL, { "GL_ARB_polygon_offset_clamp" } }, 186 [feat_robust_buffer_access] = { 43, UNAVAIL, { "GL_ARB_robust_buffer_access_behaviour" } }, 187 [feat_sample_mask] = { 32, 31, { "GL_ARB_texture_multisample" } }, 188 [feat_sample_shading] = { 40, UNAVAIL, { "GL_ARB_sample_shading" } }, 189 [feat_samplers] = { 33, 30, { "GL_ARB_sampler_objects" } }, 190 [feat_shader_clock] = { UNAVAIL, UNAVAIL, { "GL_ARB_shader_clock" } }, 191 [feat_ssbo] = { 43, 31, { "GL_ARB_shader_storage_buffer_object" } }, 192 [feat_ssbo_barrier] = { 43, 31, {} }, 193 [feat_stencil_texturing] = { 43, 31, { "GL_ARB_stencil_texturing" } }, 194 [feat_storage_multisample] = { 43, 31, { "GL_ARB_texture_storage_multisample" } }, 195 [feat_tessellation] = { 40, UNAVAIL, { "GL_ARB_tessellation_shader" } }, 196 [feat_texture_array] = { 30, 30, { "GL_EXT_texture_array" } }, 197 [feat_texture_barrier] = { 45, UNAVAIL, { "GL_ARB_texture_barrier" } }, 198 [feat_texture_buffer_range] = { 43, UNAVAIL, { "GL_ARB_texture_buffer_range" } }, 199 [feat_texture_gather] = { 40, 31, { "GL_ARB_texture_gather" } }, 200 [feat_texture_multisample] = { 32, 30, { "GL_ARB_texture_multisample" } }, 201 [feat_texture_srgb_decode] = { UNAVAIL, UNAVAIL, { "GL_EXT_texture_sRGB_decode" } }, 202 [feat_texture_storage] = { 42, 30, { "GL_ARB_texture_storage" } }, 203 [feat_texture_view] = { 43, UNAVAIL, { "GL_ARB_texture_view" } }, 204 [feat_transform_feedback] = { 30, 30, { "GL_EXT_transform_feedback" } }, 205 [feat_transform_feedback2] = { 40, 30, { "GL_ARB_transform_feedback2" } }, 206 [feat_transform_feedback3] = { 40, UNAVAIL, { "GL_ARB_transform_feedback3" } }, 207 [feat_transform_feedback_overflow_query] = { 46, UNAVAIL, { "GL_ARB_transform_feedback_overflow_query" } }, 208 [feat_txqs] = { 45, UNAVAIL, { "GL_ARB_shader_texture_image_samples" } }, 209 [feat_ubo] = { 31, 30, { "GL_ARB_uniform_buffer_object" } }, 210 [feat_viewport_array] = { 41, UNAVAIL, { "GL_ARB_viewport_array" } }, 211 }; 212 213 struct global_renderer_state { 214 int gl_major_ver; 215 int gl_minor_ver; 216 217 struct vrend_context *current_ctx; 218 struct vrend_context *current_hw_ctx; 219 struct list_head waiting_query_list; 220 221 bool inited; 222 bool use_gles; 223 bool use_core_profile; 224 225 bool features[feat_last]; 226 227 /* these appeared broken on at least one driver */ 228 bool use_explicit_locations; 229 uint32_t max_uniform_blocks; 230 uint32_t max_draw_buffers; 231 struct list_head active_ctx_list; 232 233 /* threaded sync */ 234 bool stop_sync_thread; 235 int eventfd; 236 237 pipe_mutex fence_mutex; 238 struct list_head fence_list; 239 struct list_head fence_wait_list; 240 pipe_condvar fence_cond; 241 242 pipe_thread sync_thread; 243 virgl_gl_context sync_context; 244 }; 245 246 static struct global_renderer_state vrend_state; 247 248 static inline bool has_feature(enum features_id feature_id) 249 { 250 return vrend_state.features[feature_id]; 251 } 252 253 static inline void set_feature(enum features_id feature_id) 254 { 255 vrend_state.features[feature_id] = true; 256 } 257 258 struct vrend_linked_shader_program { 259 struct list_head head; 260 struct list_head sl[PIPE_SHADER_TYPES]; 261 GLuint id; 262 263 bool dual_src_linked; 264 struct vrend_shader *ss[PIPE_SHADER_TYPES]; 265 266 uint32_t samplers_used_mask[PIPE_SHADER_TYPES]; 267 GLuint *samp_locs[PIPE_SHADER_TYPES]; 268 269 GLuint *shadow_samp_mask_locs[PIPE_SHADER_TYPES]; 270 GLuint *shadow_samp_add_locs[PIPE_SHADER_TYPES]; 271 272 GLint *const_locs[PIPE_SHADER_TYPES]; 273 274 GLuint *attrib_locs; 275 uint32_t shadow_samp_mask[PIPE_SHADER_TYPES]; 276 277 GLuint *ubo_locs[PIPE_SHADER_TYPES]; 278 GLuint vs_ws_adjust_loc; 279 280 GLint fs_stipple_loc; 281 282 GLuint clip_locs[8]; 283 284 uint32_t images_used_mask[PIPE_SHADER_TYPES]; 285 GLint *img_locs[PIPE_SHADER_TYPES]; 286 287 uint32_t ssbo_used_mask[PIPE_SHADER_TYPES]; 288 GLuint *ssbo_locs[PIPE_SHADER_TYPES]; 289 }; 290 291 struct vrend_shader { 292 struct vrend_shader *next_variant; 293 struct vrend_shader_selector *sel; 294 295 GLchar *glsl_prog; 296 GLuint id; 297 GLuint compiled_fs_id; 298 struct vrend_shader_key key; 299 struct list_head programs; 300 }; 301 302 struct vrend_shader_selector { 303 struct pipe_reference reference; 304 305 unsigned num_shaders; 306 unsigned type; 307 struct vrend_shader_info sinfo; 308 309 struct vrend_shader *current; 310 struct tgsi_token *tokens; 311 312 uint32_t req_local_mem; 313 char *tmp_buf; 314 uint32_t buf_len; 315 uint32_t buf_offset; 316 }; 317 318 struct vrend_texture { 319 struct vrend_resource base; 320 struct pipe_sampler_state state; 321 }; 322 323 struct vrend_surface { 324 struct pipe_reference reference; 325 GLuint id; 326 GLuint res_handle; 327 GLuint format; 328 GLuint val0, val1; 329 struct vrend_resource *texture; 330 }; 331 332 struct vrend_sampler_state { 333 struct pipe_sampler_state base; 334 GLuint id; 335 }; 336 337 struct vrend_so_target { 338 struct pipe_reference reference; 339 GLuint res_handle; 340 unsigned buffer_offset; 341 unsigned buffer_size; 342 struct vrend_resource *buffer; 343 struct vrend_sub_context *sub_ctx; 344 }; 345 346 struct vrend_sampler_view { 347 struct pipe_reference reference; 348 GLuint id; 349 GLuint format; 350 GLenum target; 351 GLuint val0, val1; 352 GLuint gl_swizzle_r; 353 GLuint gl_swizzle_g; 354 GLuint gl_swizzle_b; 355 GLuint gl_swizzle_a; 356 GLenum cur_swizzle_r; 357 GLenum cur_swizzle_g; 358 GLenum cur_swizzle_b; 359 GLenum cur_swizzle_a; 360 GLuint cur_base, cur_max; 361 GLenum depth_texture_mode; 362 GLuint srgb_decode; 363 GLuint cur_srgb_decode; 364 struct vrend_resource *texture; 365 }; 366 367 struct vrend_image_view { 368 GLuint id; 369 GLenum access; 370 GLenum format; 371 union { 372 struct { 373 unsigned first_layer:16; /**< first layer to use for array textures */ 374 unsigned last_layer:16; /**< last layer to use for array textures */ 375 unsigned level:8; /**< mipmap level to use */ 376 } tex; 377 struct { 378 unsigned offset; /**< offset in bytes */ 379 unsigned size; /**< size of the accessible sub-range in bytes */ 380 } buf; 381 } u; 382 struct vrend_resource *texture; 383 }; 384 385 struct vrend_ssbo { 386 struct vrend_resource *res; 387 unsigned buffer_size; 388 unsigned buffer_offset; 389 }; 390 391 struct vrend_vertex_element { 392 struct pipe_vertex_element base; 393 GLenum type; 394 GLboolean norm; 395 GLuint nr_chan; 396 }; 397 398 struct vrend_vertex_element_array { 399 unsigned count; 400 struct vrend_vertex_element elements[PIPE_MAX_ATTRIBS]; 401 GLuint id; 402 }; 403 404 struct vrend_constants { 405 unsigned int *consts; 406 uint32_t num_consts; 407 }; 408 409 struct vrend_shader_view { 410 int num_views; 411 struct vrend_sampler_view *views[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 412 uint32_t res_id[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 413 uint32_t old_ids[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 414 }; 415 416 struct vrend_viewport { 417 GLint cur_x, cur_y; 418 GLsizei width, height; 419 GLclampd near_val, far_val; 420 }; 421 422 /* create a streamout object to support pause/resume */ 423 struct vrend_streamout_object { 424 GLuint id; 425 uint32_t num_targets; 426 uint32_t handles[16]; 427 struct list_head head; 428 int xfb_state; 429 struct vrend_so_target *so_targets[16]; 430 }; 431 432 #define XFB_STATE_OFF 0 433 #define XFB_STATE_STARTED_NEED_BEGIN 1 434 #define XFB_STATE_STARTED 2 435 #define XFB_STATE_PAUSED 3 436 437 struct vrend_sub_context { 438 struct list_head head; 439 440 virgl_gl_context gl_context; 441 442 int sub_ctx_id; 443 444 GLuint vaoid; 445 uint32_t enabled_attribs_bitmask; 446 447 struct list_head programs; 448 struct util_hash_table *object_hash; 449 450 struct vrend_vertex_element_array *ve; 451 int num_vbos; 452 int old_num_vbos; /* for cleaning up */ 453 struct pipe_vertex_buffer vbo[PIPE_MAX_ATTRIBS]; 454 uint32_t vbo_res_ids[PIPE_MAX_ATTRIBS]; 455 456 struct pipe_index_buffer ib; 457 uint32_t index_buffer_res_id; 458 459 bool vbo_dirty; 460 bool shader_dirty; 461 bool cs_shader_dirty; 462 bool sampler_state_dirty; 463 bool stencil_state_dirty; 464 bool image_state_dirty; 465 466 uint32_t long_shader_in_progress_handle[PIPE_SHADER_TYPES]; 467 struct vrend_shader_selector *shaders[PIPE_SHADER_TYPES]; 468 struct vrend_linked_shader_program *prog; 469 470 int prog_ids[PIPE_SHADER_TYPES]; 471 struct vrend_shader_view views[PIPE_SHADER_TYPES]; 472 473 struct vrend_constants consts[PIPE_SHADER_TYPES]; 474 bool const_dirty[PIPE_SHADER_TYPES]; 475 struct vrend_sampler_state *sampler_state[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; 476 477 struct pipe_constant_buffer cbs[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; 478 uint32_t const_bufs_used_mask[PIPE_SHADER_TYPES]; 479 480 int num_sampler_states[PIPE_SHADER_TYPES]; 481 482 uint32_t fb_id; 483 int nr_cbufs, old_nr_cbufs; 484 struct vrend_surface *zsurf; 485 struct vrend_surface *surf[PIPE_MAX_COLOR_BUFS]; 486 487 struct vrend_viewport vps[PIPE_MAX_VIEWPORTS]; 488 float depth_transform, depth_scale; 489 /* viewport is negative */ 490 uint32_t scissor_state_dirty; 491 uint32_t viewport_state_dirty; 492 493 uint32_t fb_height; 494 495 struct pipe_scissor_state ss[PIPE_MAX_VIEWPORTS]; 496 497 struct pipe_blend_state blend_state; 498 struct pipe_depth_stencil_alpha_state dsa_state; 499 struct pipe_rasterizer_state rs_state; 500 501 uint8_t stencil_refs[2]; 502 bool viewport_is_negative; 503 /* this is set if the contents of the FBO look upside down when viewed 504 with 0,0 as the bottom corner */ 505 bool inverted_fbo_content; 506 507 GLuint blit_fb_ids[2]; 508 509 struct pipe_depth_stencil_alpha_state *dsa; 510 511 struct pipe_clip_state ucp_state; 512 513 bool blend_enabled; 514 bool depth_test_enabled; 515 bool alpha_test_enabled; 516 bool stencil_test_enabled; 517 518 GLuint program_id; 519 int last_shader_idx; 520 521 struct pipe_rasterizer_state hw_rs_state; 522 struct pipe_blend_state hw_blend_state; 523 524 struct list_head streamout_list; 525 struct vrend_streamout_object *current_so; 526 527 struct pipe_blend_color blend_color; 528 529 uint32_t cond_render_q_id; 530 GLenum cond_render_gl_mode; 531 532 struct vrend_image_view image_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES]; 533 uint32_t images_used_mask[PIPE_SHADER_TYPES]; 534 535 struct vrend_ssbo ssbo[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS]; 536 uint32_t ssbo_used_mask[PIPE_SHADER_TYPES]; 537 }; 538 539 struct vrend_context { 540 char debug_name[64]; 541 542 struct list_head sub_ctxs; 543 544 struct vrend_sub_context *sub; 545 struct vrend_sub_context *sub0; 546 547 int ctx_id; 548 /* has this ctx gotten an error? */ 549 bool in_error; 550 bool ctx_switch_pending; 551 bool pstip_inited; 552 553 GLuint pstipple_tex_id; 554 555 enum virgl_ctx_errors last_error; 556 557 /* resource bounds to this context */ 558 struct util_hash_table *res_hash; 559 560 struct list_head active_nontimer_query_list; 561 struct list_head ctx_entry; 562 563 struct vrend_shader_cfg shader_cfg; 564 }; 565 566 static struct vrend_resource *vrend_renderer_ctx_res_lookup(struct vrend_context *ctx, int res_handle); 567 static void vrend_pause_render_condition(struct vrend_context *ctx, bool pause); 568 static void vrend_update_viewport_state(struct vrend_context *ctx); 569 static void vrend_update_scissor_state(struct vrend_context *ctx); 570 static void vrend_destroy_query_object(void *obj_ptr); 571 static void vrend_finish_context_switch(struct vrend_context *ctx); 572 static void vrend_patch_blend_state(struct vrend_context *ctx); 573 static void vrend_update_frontface_state(struct vrend_context *ctx); 574 static void vrender_get_glsl_version(int *glsl_version); 575 static void vrend_destroy_resource_object(void *obj_ptr); 576 static void vrend_renderer_detach_res_ctx_p(struct vrend_context *ctx, int res_handle); 577 static void vrend_destroy_program(struct vrend_linked_shader_program *ent); 578 static void vrend_apply_sampler_state(struct vrend_context *ctx, 579 struct vrend_resource *res, 580 uint32_t shader_type, 581 int id, int sampler_id, uint32_t srgb_decode); 582 static GLenum tgsitargettogltarget(const enum pipe_texture_target target, int nr_samples); 583 584 void vrend_update_stencil_state(struct vrend_context *ctx); 585 586 static struct vrend_format_table tex_conv_table[VIRGL_FORMAT_MAX]; 587 588 static inline bool vrend_format_can_sample(enum virgl_formats format) 589 { 590 return tex_conv_table[format].bindings & VIRGL_BIND_SAMPLER_VIEW; 591 } 592 static inline bool vrend_format_can_render(enum virgl_formats format) 593 { 594 return tex_conv_table[format].bindings & VIRGL_BIND_RENDER_TARGET; 595 } 596 597 static inline bool vrend_format_is_ds(enum virgl_formats format) 598 { 599 return tex_conv_table[format].bindings & VIRGL_BIND_DEPTH_STENCIL; 600 } 601 602 bool vrend_is_ds_format(enum virgl_formats format) 603 { 604 return vrend_format_is_ds(format); 605 } 606 607 bool vrend_format_is_emulated_alpha(enum virgl_formats format) 608 { 609 if (!vrend_state.use_core_profile) 610 return false; 611 return (format == VIRGL_FORMAT_A8_UNORM || 612 format == VIRGL_FORMAT_A16_UNORM); 613 } 614 615 static bool vrend_format_needs_swizzle(enum virgl_formats format) 616 { 617 return tex_conv_table[format].flags & VIRGL_BIND_NEED_SWIZZLE; 618 } 619 620 static inline const char *pipe_shader_to_prefix(int shader_type) 621 { 622 switch (shader_type) { 623 case PIPE_SHADER_VERTEX: return "vs"; 624 case PIPE_SHADER_FRAGMENT: return "fs"; 625 case PIPE_SHADER_GEOMETRY: return "gs"; 626 case PIPE_SHADER_TESS_CTRL: return "tc"; 627 case PIPE_SHADER_TESS_EVAL: return "te"; 628 case PIPE_SHADER_COMPUTE: return "cs"; 629 default: 630 return NULL; 631 }; 632 } 633 634 static const char *vrend_ctx_error_strings[] = { "None", "Unknown", "Illegal shader", "Illegal handle", "Illegal resource", "Illegal surface", "Illegal vertex format", "Illegal command buffer" }; 635 636 static void __report_context_error(const char *fname, struct vrend_context *ctx, enum virgl_ctx_errors error, uint32_t value) 637 { 638 ctx->in_error = true; 639 ctx->last_error = error; 640 fprintf(stderr,"%s: context error reported %d \"%s\" %s %d\n", fname, ctx->ctx_id, ctx->debug_name, vrend_ctx_error_strings[error], value); 641 } 642 #define report_context_error(ctx, error, value) __report_context_error(__func__, ctx, error, value) 643 644 void vrend_report_buffer_error(struct vrend_context *ctx, int cmd) 645 { 646 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, cmd); 647 } 648 649 #define CORE_PROFILE_WARN_NONE 0 650 #define CORE_PROFILE_WARN_STIPPLE 1 651 #define CORE_PROFILE_WARN_POLYGON_MODE 2 652 #define CORE_PROFILE_WARN_TWO_SIDE 3 653 #define CORE_PROFILE_WARN_CLAMP 4 654 #define CORE_PROFILE_WARN_SHADE_MODEL 5 655 656 static const char *vrend_core_profile_warn_strings[] = { "None", "Stipple", "Polygon Mode", "Two Side", "Clamping", "Shade Model" }; 657 658 static void __report_core_warn(const char *fname, struct vrend_context *ctx, enum virgl_ctx_errors error, uint32_t value) 659 { 660 fprintf(stderr,"%s: core profile violation reported %d \"%s\" %s %d\n", fname, ctx->ctx_id, ctx->debug_name, vrend_core_profile_warn_strings[error], value); 661 } 662 #define report_core_warn(ctx, error, value) __report_core_warn(__func__, ctx, error, value) 663 664 665 #define GLES_WARN_NONE 0 666 #define GLES_WARN_STIPPLE 1 667 #define GLES_WARN_POLYGON_MODE 2 668 #define GLES_WARN_DEPTH_RANGE 3 669 #define GLES_WARN_POINT_SIZE 4 670 #define GLES_WARN_LOD_BIAS 5 671 //#define GLES_WARN_ free slot 6 672 #define GLES_WARN_TEXTURE_RECT 7 673 #define GLES_WARN_OFFSET_LINE 8 674 #define GLES_WARN_OFFSET_POINT 9 675 #define GLES_WARN_DEPTH_CLIP 10 676 #define GLES_WARN_FLATSHADE_FIRST 11 677 #define GLES_WARN_LINE_SMOOTH 12 678 #define GLES_WARN_POLY_SMOOTH 13 679 #define GLES_WARN_DEPTH_CLEAR 14 680 #define GLES_WARN_LOGIC_OP 15 681 #define GLES_WARN_TIMESTAMP 16 682 683 static const char *vrend_gles_warn_strings[] = { 684 "None", "Stipple", "Polygon Mode", "Depth Range", "Point Size", "Lod Bias", 685 "<<WARNING #6>>", "Texture Rect", "Offset Line", "Offset Point", 686 "Depth Clip", "Flatshade First", "Line Smooth", "Poly Smooth", 687 "Depth Clear", "LogicOp", "GL_TIMESTAMP" 688 }; 689 690 static void __report_gles_warn(const char *fname, struct vrend_context *ctx, enum virgl_ctx_errors error, uint32_t value) 691 { 692 int id = ctx ? ctx->ctx_id : -1; 693 const char *name = ctx ? ctx->debug_name : "NO_CONTEXT"; 694 fprintf(stderr,"%s: gles violation reported %d \"%s\" %s %d\n", fname, id, name, vrend_gles_warn_strings[error], value); 695 } 696 #define report_gles_warn(ctx, error, value) __report_gles_warn(__func__, ctx, error, value) 697 698 static void __report_gles_missing_func(const char *fname, struct vrend_context *ctx, const char *missf) 699 { 700 int id = ctx ? ctx->ctx_id : -1; 701 const char *name = ctx ? ctx->debug_name : "NO_CONTEXT"; 702 fprintf(stderr,"%s: gles violation reported %d \"%s\" %s is missing\n", fname, id, name, missf); 703 } 704 #define report_gles_missing_func(ctx, missf) __report_gles_missing_func(__func__, ctx, missf) 705 706 static void init_features(int gl_ver, int gles_ver) 707 { 708 for (enum features_id id = 0; id < feat_last; id++) { 709 if (gl_ver >= feature_list[id].gl_ver || 710 gles_ver >= feature_list[id].gles_ver) 711 set_feature(id); 712 else { 713 for (uint32_t i = 0; i < FEAT_MAX_EXTS; i++) { 714 if (!feature_list[id].gl_ext[i]) 715 break; 716 if (epoxy_has_gl_extension(feature_list[id].gl_ext[i])) { 717 set_feature(id); 718 break; 719 } 720 } 721 } 722 } 723 } 724 725 static void vrend_destroy_surface(struct vrend_surface *surf) 726 { 727 if (surf->id != surf->texture->id) 728 glDeleteTextures(1, &surf->id); 729 vrend_resource_reference(&surf->texture, NULL); 730 free(surf); 731 } 732 733 static inline void 734 vrend_surface_reference(struct vrend_surface **ptr, struct vrend_surface *surf) 735 { 736 struct vrend_surface *old_surf = *ptr; 737 738 if (pipe_reference(&(*ptr)->reference, &surf->reference)) 739 vrend_destroy_surface(old_surf); 740 *ptr = surf; 741 } 742 743 static void vrend_destroy_sampler_view(struct vrend_sampler_view *samp) 744 { 745 if (samp->texture->id != samp->id) 746 glDeleteTextures(1, &samp->id); 747 vrend_resource_reference(&samp->texture, NULL); 748 free(samp); 749 } 750 751 static inline void 752 vrend_sampler_view_reference(struct vrend_sampler_view **ptr, struct vrend_sampler_view *view) 753 { 754 struct vrend_sampler_view *old_view = *ptr; 755 756 if (pipe_reference(&(*ptr)->reference, &view->reference)) 757 vrend_destroy_sampler_view(old_view); 758 *ptr = view; 759 } 760 761 static void vrend_destroy_so_target(struct vrend_so_target *target) 762 { 763 vrend_resource_reference(&target->buffer, NULL); 764 free(target); 765 } 766 767 static inline void 768 vrend_so_target_reference(struct vrend_so_target **ptr, struct vrend_so_target *target) 769 { 770 struct vrend_so_target *old_target = *ptr; 771 772 if (pipe_reference(&(*ptr)->reference, &target->reference)) 773 vrend_destroy_so_target(old_target); 774 *ptr = target; 775 } 776 777 static void vrend_shader_destroy(struct vrend_shader *shader) 778 { 779 struct vrend_linked_shader_program *ent, *tmp; 780 781 LIST_FOR_EACH_ENTRY_SAFE(ent, tmp, &shader->programs, sl[shader->sel->type]) { 782 vrend_destroy_program(ent); 783 } 784 785 glDeleteShader(shader->id); 786 free(shader->glsl_prog); 787 free(shader); 788 } 789 790 static void vrend_destroy_shader_selector(struct vrend_shader_selector *sel) 791 { 792 struct vrend_shader *p = sel->current, *c; 793 unsigned i; 794 while (p) { 795 c = p->next_variant; 796 vrend_shader_destroy(p); 797 p = c; 798 } 799 if (sel->sinfo.so_names) 800 for (i = 0; i < sel->sinfo.so_info.num_outputs; i++) 801 free(sel->sinfo.so_names[i]); 802 free(sel->tmp_buf); 803 free(sel->sinfo.so_names); 804 free(sel->sinfo.interpinfo); 805 free(sel->sinfo.sampler_arrays); 806 free(sel->sinfo.image_arrays); 807 free(sel->tokens); 808 free(sel); 809 } 810 811 static bool vrend_compile_shader(struct vrend_context *ctx, 812 struct vrend_shader *shader) 813 { 814 GLint param; 815 glShaderSource(shader->id, 1, (const char **)&shader->glsl_prog, NULL); 816 glCompileShader(shader->id); 817 glGetShaderiv(shader->id, GL_COMPILE_STATUS, ¶m); 818 if (param == GL_FALSE) { 819 char infolog[65536]; 820 int len; 821 glGetShaderInfoLog(shader->id, 65536, &len, infolog); 822 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SHADER, 0); 823 fprintf(stderr,"shader failed to compile\n%s\n", infolog); 824 fprintf(stderr,"GLSL:\n%s\n", shader->glsl_prog); 825 return false; 826 } 827 return true; 828 } 829 830 static inline void 831 vrend_shader_state_reference(struct vrend_shader_selector **ptr, struct vrend_shader_selector *shader) 832 { 833 struct vrend_shader_selector *old_shader = *ptr; 834 835 if (pipe_reference(&(*ptr)->reference, &shader->reference)) 836 vrend_destroy_shader_selector(old_shader); 837 *ptr = shader; 838 } 839 840 void 841 vrend_insert_format(struct vrend_format_table *entry, uint32_t bindings) 842 { 843 tex_conv_table[entry->format] = *entry; 844 tex_conv_table[entry->format].bindings = bindings; 845 } 846 847 void 848 vrend_insert_format_swizzle(int override_format, struct vrend_format_table *entry, uint32_t bindings, uint8_t swizzle[4]) 849 { 850 int i; 851 tex_conv_table[override_format] = *entry; 852 tex_conv_table[override_format].bindings = bindings; 853 tex_conv_table[override_format].flags = VIRGL_BIND_NEED_SWIZZLE; 854 for (i = 0; i < 4; i++) 855 tex_conv_table[override_format].swizzle[i] = swizzle[i]; 856 } 857 858 const struct vrend_format_table * 859 vrend_get_format_table_entry(enum virgl_formats format) 860 { 861 return &tex_conv_table[format]; 862 } 863 864 static bool vrend_is_timer_query(GLenum gltype) 865 { 866 return gltype == GL_TIMESTAMP || 867 gltype == GL_TIME_ELAPSED; 868 } 869 870 static void vrend_use_program(struct vrend_context *ctx, GLuint program_id) 871 { 872 if (ctx->sub->program_id != program_id) { 873 glUseProgram(program_id); 874 ctx->sub->program_id = program_id; 875 } 876 } 877 878 static void vrend_init_pstipple_texture(struct vrend_context *ctx) 879 { 880 glGenTextures(1, &ctx->pstipple_tex_id); 881 glBindTexture(GL_TEXTURE_2D, ctx->pstipple_tex_id); 882 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 32, 0, GL_RED, GL_UNSIGNED_BYTE, NULL); 883 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 884 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 885 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 886 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 887 888 ctx->pstip_inited = true; 889 } 890 891 static void vrend_blend_enable(struct vrend_context *ctx, bool blend_enable) 892 { 893 if (ctx->sub->blend_enabled != blend_enable) { 894 ctx->sub->blend_enabled = blend_enable; 895 if (blend_enable) 896 glEnable(GL_BLEND); 897 else 898 glDisable(GL_BLEND); 899 } 900 } 901 902 static void vrend_depth_test_enable(struct vrend_context *ctx, bool depth_test_enable) 903 { 904 if (ctx->sub->depth_test_enabled != depth_test_enable) { 905 ctx->sub->depth_test_enabled = depth_test_enable; 906 if (depth_test_enable) 907 glEnable(GL_DEPTH_TEST); 908 else 909 glDisable(GL_DEPTH_TEST); 910 } 911 } 912 913 static void vrend_alpha_test_enable(struct vrend_context *ctx, bool alpha_test_enable) 914 { 915 if (vrend_state.use_core_profile) { 916 /* handled in shaders */ 917 return; 918 } 919 if (ctx->sub->alpha_test_enabled != alpha_test_enable) { 920 ctx->sub->alpha_test_enabled = alpha_test_enable; 921 if (alpha_test_enable) 922 glEnable(GL_ALPHA_TEST); 923 else 924 glDisable(GL_ALPHA_TEST); 925 } 926 } 927 928 static void vrend_stencil_test_enable(struct vrend_context *ctx, bool stencil_test_enable) 929 { 930 if (ctx->sub->stencil_test_enabled != stencil_test_enable) { 931 ctx->sub->stencil_test_enabled = stencil_test_enable; 932 if (stencil_test_enable) 933 glEnable(GL_STENCIL_TEST); 934 else 935 glDisable(GL_STENCIL_TEST); 936 } 937 } 938 939 static void dump_stream_out(struct pipe_stream_output_info *so) 940 { 941 unsigned i; 942 if (!so) 943 return; 944 printf("streamout: %d\n", so->num_outputs); 945 printf("strides: "); 946 for (i = 0; i < 4; i++) 947 printf("%d ", so->stride[i]); 948 printf("\n"); 949 printf("outputs:\n"); 950 for (i = 0; i < so->num_outputs; i++) { 951 printf("\t%d: reg: %d sc: %d, nc: %d ob: %d do: %d st: %d\n", 952 i, 953 so->output[i].register_index, 954 so->output[i].start_component, 955 so->output[i].num_components, 956 so->output[i].output_buffer, 957 so->output[i].dst_offset, 958 so->output[i].stream); 959 } 960 } 961 962 static char *get_skip_str(int *skip_val) 963 { 964 char *start_skip = NULL; 965 if (*skip_val < 0) { 966 *skip_val = 0; 967 return NULL; 968 } 969 970 if (*skip_val == 1) { 971 start_skip = strdup("gl_SkipComponents1"); 972 *skip_val -= 1; 973 } else if (*skip_val == 2) { 974 start_skip = strdup("gl_SkipComponents2"); 975 *skip_val -= 2; 976 } else if (*skip_val == 3) { 977 start_skip = strdup("gl_SkipComponents3"); 978 *skip_val -= 3; 979 } else if (*skip_val >= 4) { 980 start_skip = strdup("gl_SkipComponents4"); 981 *skip_val -= 4; 982 } 983 return start_skip; 984 } 985 986 static void set_stream_out_varyings(int prog_id, struct vrend_shader_info *sinfo) 987 { 988 struct pipe_stream_output_info *so = &sinfo->so_info; 989 char *varyings[PIPE_MAX_SHADER_OUTPUTS*2]; 990 int j; 991 uint i, n_outputs = 0; 992 int last_buffer = 0; 993 char *start_skip; 994 int buf_offset = 0; 995 int skip; 996 if (!so->num_outputs) 997 return; 998 999 if (vrend_dump_shaders) 1000 dump_stream_out(so); 1001 1002 for (i = 0; i < so->num_outputs; i++) { 1003 if (last_buffer != so->output[i].output_buffer) { 1004 1005 skip = so->stride[last_buffer] - buf_offset; 1006 while (skip) { 1007 start_skip = get_skip_str(&skip); 1008 if (start_skip) 1009 varyings[n_outputs++] = start_skip; 1010 } 1011 for (j = last_buffer; j < so->output[i].output_buffer; j++) 1012 varyings[n_outputs++] = strdup("gl_NextBuffer"); 1013 last_buffer = so->output[i].output_buffer; 1014 buf_offset = 0; 1015 } 1016 1017 skip = so->output[i].dst_offset - buf_offset; 1018 while (skip) { 1019 start_skip = get_skip_str(&skip); 1020 if (start_skip) 1021 varyings[n_outputs++] = start_skip; 1022 } 1023 buf_offset = so->output[i].dst_offset; 1024 1025 buf_offset += so->output[i].num_components; 1026 if (sinfo->so_names[i]) 1027 varyings[n_outputs++] = strdup(sinfo->so_names[i]); 1028 } 1029 1030 skip = so->stride[last_buffer] - buf_offset; 1031 while (skip) { 1032 start_skip = get_skip_str(&skip); 1033 if (start_skip) 1034 varyings[n_outputs++] = start_skip; 1035 } 1036 1037 glTransformFeedbackVaryings(prog_id, n_outputs, 1038 (const GLchar **)varyings, GL_INTERLEAVED_ATTRIBS_EXT); 1039 1040 for (i = 0; i < n_outputs; i++) 1041 if (varyings[i]) 1042 free(varyings[i]); 1043 } 1044 1045 static void bind_sampler_locs(struct vrend_linked_shader_program *sprog, 1046 int id) 1047 { 1048 if (sprog->ss[id]->sel->sinfo.samplers_used_mask) { 1049 uint32_t mask = sprog->ss[id]->sel->sinfo.samplers_used_mask; 1050 int nsamp = util_bitcount(sprog->ss[id]->sel->sinfo.samplers_used_mask); 1051 int index; 1052 sprog->shadow_samp_mask[id] = sprog->ss[id]->sel->sinfo.shadow_samp_mask; 1053 if (sprog->ss[id]->sel->sinfo.shadow_samp_mask) { 1054 sprog->shadow_samp_mask_locs[id] = calloc(nsamp, sizeof(uint32_t)); 1055 sprog->shadow_samp_add_locs[id] = calloc(nsamp, sizeof(uint32_t)); 1056 } else { 1057 sprog->shadow_samp_mask_locs[id] = sprog->shadow_samp_add_locs[id] = NULL; 1058 } 1059 sprog->samp_locs[id] = calloc(nsamp, sizeof(uint32_t)); 1060 if (sprog->samp_locs[id]) { 1061 const char *prefix = pipe_shader_to_prefix(id); 1062 index = 0; 1063 while(mask) { 1064 uint32_t i = u_bit_scan(&mask); 1065 char name[64]; 1066 if (sprog->ss[id]->sel->sinfo.num_sampler_arrays) { 1067 int arr_idx = shader_lookup_sampler_array(&sprog->ss[id]->sel->sinfo, i); 1068 snprintf(name, 32, "%ssamp%d[%d]", prefix, arr_idx, i - arr_idx); 1069 } else 1070 snprintf(name, 32, "%ssamp%d", prefix, i); 1071 sprog->samp_locs[id][index] = glGetUniformLocation(sprog->id, name); 1072 if (sprog->ss[id]->sel->sinfo.shadow_samp_mask & (1 << i)) { 1073 snprintf(name, 32, "%sshadmask%d", prefix, i); 1074 sprog->shadow_samp_mask_locs[id][index] = glGetUniformLocation(sprog->id, name); 1075 snprintf(name, 32, "%sshadadd%d", prefix, i); 1076 sprog->shadow_samp_add_locs[id][index] = glGetUniformLocation(sprog->id, name); 1077 } 1078 index++; 1079 } 1080 } 1081 } else { 1082 sprog->samp_locs[id] = NULL; 1083 sprog->shadow_samp_mask_locs[id] = NULL; 1084 sprog->shadow_samp_add_locs[id] = NULL; 1085 sprog->shadow_samp_mask[id] = 0; 1086 } 1087 sprog->samplers_used_mask[id] = sprog->ss[id]->sel->sinfo.samplers_used_mask; 1088 } 1089 1090 static void bind_const_locs(struct vrend_linked_shader_program *sprog, 1091 int id) 1092 { 1093 if (sprog->ss[id]->sel->sinfo.num_consts) { 1094 sprog->const_locs[id] = calloc(sprog->ss[id]->sel->sinfo.num_consts, sizeof(uint32_t)); 1095 if (sprog->const_locs[id]) { 1096 const char *prefix = pipe_shader_to_prefix(id); 1097 for (int i = 0; i < sprog->ss[id]->sel->sinfo.num_consts; i++) { 1098 char name[32]; 1099 snprintf(name, 32, "%sconst0[%d]", prefix, i); 1100 sprog->const_locs[id][i] = glGetUniformLocation(sprog->id, name); 1101 } 1102 } 1103 } else 1104 sprog->const_locs[id] = NULL; 1105 } 1106 1107 static void bind_ubo_locs(struct vrend_linked_shader_program *sprog, 1108 int id) 1109 { 1110 if (!has_feature(feat_ubo)) 1111 return; 1112 if (sprog->ss[id]->sel->sinfo.num_ubos) { 1113 const char *prefix = pipe_shader_to_prefix(id); 1114 1115 sprog->ubo_locs[id] = calloc(sprog->ss[id]->sel->sinfo.num_ubos, sizeof(uint32_t)); 1116 for (int i = 0; i < sprog->ss[id]->sel->sinfo.num_ubos; i++) { 1117 int ubo_idx = sprog->ss[id]->sel->sinfo.ubo_idx[i]; 1118 char name[32]; 1119 if (sprog->ss[id]->sel->sinfo.ubo_indirect) 1120 snprintf(name, 32, "%subo[%d]", prefix, ubo_idx - 1); 1121 else 1122 snprintf(name, 32, "%subo%d", prefix, ubo_idx); 1123 1124 sprog->ubo_locs[id][i] = glGetUniformBlockIndex(sprog->id, name); 1125 } 1126 } else 1127 sprog->ubo_locs[id] = NULL; 1128 } 1129 1130 static void bind_ssbo_locs(struct vrend_linked_shader_program *sprog, 1131 int id) 1132 { 1133 int i; 1134 char name[32]; 1135 if (!has_feature(feat_ssbo)) 1136 return; 1137 if (sprog->ss[id]->sel->sinfo.ssbo_used_mask) { 1138 const char *prefix = pipe_shader_to_prefix(id); 1139 uint32_t mask = sprog->ss[id]->sel->sinfo.ssbo_used_mask; 1140 sprog->ssbo_locs[id] = calloc(util_last_bit(mask), sizeof(uint32_t)); 1141 1142 while (mask) { 1143 i = u_bit_scan(&mask); 1144 snprintf(name, 32, "%sssbo%d", prefix, i); 1145 sprog->ssbo_locs[id][i] = glGetProgramResourceIndex(sprog->id, GL_SHADER_STORAGE_BLOCK, name); 1146 } 1147 } else 1148 sprog->ssbo_locs[id] = NULL; 1149 sprog->ssbo_used_mask[id] = sprog->ss[id]->sel->sinfo.ssbo_used_mask; 1150 } 1151 1152 static void bind_image_locs(struct vrend_linked_shader_program *sprog, 1153 int id) 1154 { 1155 int i; 1156 char name[32]; 1157 const char *prefix = pipe_shader_to_prefix(id); 1158 1159 if (!has_feature(feat_images)) 1160 return; 1161 1162 uint32_t mask = sprog->ss[id]->sel->sinfo.images_used_mask; 1163 int nsamp = util_last_bit(mask); 1164 if (nsamp) { 1165 sprog->img_locs[id] = calloc(nsamp, sizeof(GLint)); 1166 if (!sprog->img_locs[id]) 1167 return; 1168 } else 1169 sprog->img_locs[id] = NULL; 1170 1171 if (sprog->ss[id]->sel->sinfo.num_image_arrays) { 1172 for (i = 0; i < sprog->ss[id]->sel->sinfo.num_image_arrays; i++) { 1173 struct vrend_array *img_array = &sprog->ss[id]->sel->sinfo.image_arrays[i]; 1174 for (int j = 0; j < img_array->array_size; j++) { 1175 snprintf(name, 32, "%simg%d[%d]", prefix, img_array->first, j); 1176 sprog->img_locs[id][img_array->first + j] = glGetUniformLocation(sprog->id, name); 1177 if (sprog->img_locs[id][img_array->first + j] == -1) 1178 fprintf(stderr, "failed to get uniform loc for image %s\n", name); 1179 } 1180 } 1181 } else if (mask) { 1182 for (i = 0; i < nsamp; i++) { 1183 if (mask & (1 << i)) { 1184 snprintf(name, 32, "%simg%d", prefix, i); 1185 sprog->img_locs[id][i] = glGetUniformLocation(sprog->id, name); 1186 if (sprog->img_locs[id][i] == -1) 1187 fprintf(stderr, "failed to get uniform loc for image %s\n", name); 1188 } else { 1189 sprog->img_locs[id][i] = -1; 1190 } 1191 } 1192 } 1193 sprog->images_used_mask[id] = mask; 1194 } 1195 1196 static struct vrend_linked_shader_program *add_cs_shader_program(struct vrend_context *ctx, 1197 struct vrend_shader *cs) 1198 { 1199 struct vrend_linked_shader_program *sprog = CALLOC_STRUCT(vrend_linked_shader_program); 1200 GLuint prog_id; 1201 GLint lret; 1202 prog_id = glCreateProgram(); 1203 glAttachShader(prog_id, cs->id); 1204 glLinkProgram(prog_id); 1205 1206 glGetProgramiv(prog_id, GL_LINK_STATUS, &lret); 1207 if (lret == GL_FALSE) { 1208 char infolog[65536]; 1209 int len; 1210 glGetProgramInfoLog(prog_id, 65536, &len, infolog); 1211 fprintf(stderr,"got error linking\n%s\n", infolog); 1212 /* dump shaders */ 1213 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SHADER, 0); 1214 fprintf(stderr,"compute shader: %d GLSL\n%s\n", cs->id, cs->glsl_prog); 1215 glDeleteProgram(prog_id); 1216 free(sprog); 1217 return NULL; 1218 } 1219 sprog->ss[PIPE_SHADER_COMPUTE] = cs; 1220 1221 list_add(&sprog->sl[PIPE_SHADER_COMPUTE], &cs->programs); 1222 sprog->id = prog_id; 1223 list_addtail(&sprog->head, &ctx->sub->programs); 1224 1225 bind_sampler_locs(sprog, PIPE_SHADER_COMPUTE); 1226 bind_ubo_locs(sprog, PIPE_SHADER_COMPUTE); 1227 bind_ssbo_locs(sprog, PIPE_SHADER_COMPUTE); 1228 bind_const_locs(sprog, PIPE_SHADER_COMPUTE); 1229 bind_image_locs(sprog, PIPE_SHADER_COMPUTE); 1230 return sprog; 1231 } 1232 1233 static struct vrend_linked_shader_program *add_shader_program(struct vrend_context *ctx, 1234 struct vrend_shader *vs, 1235 struct vrend_shader *fs, 1236 struct vrend_shader *gs, 1237 struct vrend_shader *tcs, 1238 struct vrend_shader *tes) 1239 { 1240 struct vrend_linked_shader_program *sprog = CALLOC_STRUCT(vrend_linked_shader_program); 1241 char name[64]; 1242 int i; 1243 GLuint prog_id; 1244 GLint lret; 1245 int id; 1246 int last_shader; 1247 bool do_patch = false; 1248 if (!sprog) 1249 return NULL; 1250 1251 /* need to rewrite VS code to add interpolation params */ 1252 if (gs && gs->compiled_fs_id != fs->id) 1253 do_patch = true; 1254 if (!gs && tes && tes->compiled_fs_id != fs->id) 1255 do_patch = true; 1256 if (!gs && !tes && vs->compiled_fs_id != fs->id) 1257 do_patch = true; 1258 1259 if (do_patch) { 1260 bool ret; 1261 1262 if (gs) 1263 vrend_patch_vertex_shader_interpolants(&ctx->shader_cfg, gs->glsl_prog, 1264 &gs->sel->sinfo, 1265 &fs->sel->sinfo, "gso", fs->key.flatshade); 1266 else if (tes) 1267 vrend_patch_vertex_shader_interpolants(&ctx->shader_cfg, tes->glsl_prog, 1268 &tes->sel->sinfo, 1269 &fs->sel->sinfo, "teo", fs->key.flatshade); 1270 else 1271 vrend_patch_vertex_shader_interpolants(&ctx->shader_cfg, vs->glsl_prog, 1272 &vs->sel->sinfo, 1273 &fs->sel->sinfo, "vso", fs->key.flatshade); 1274 ret = vrend_compile_shader(ctx, gs ? gs : (tes ? tes : vs)); 1275 if (ret == false) { 1276 glDeleteShader(gs ? gs->id : (tes ? tes->id : vs->id)); 1277 free(sprog); 1278 return NULL; 1279 } 1280 if (gs) 1281 gs->compiled_fs_id = fs->id; 1282 else if (tes) 1283 tes->compiled_fs_id = fs->id; 1284 else 1285 vs->compiled_fs_id = fs->id; 1286 } 1287 1288 prog_id = glCreateProgram(); 1289 glAttachShader(prog_id, vs->id); 1290 if (tcs && tcs->id > 0) 1291 glAttachShader(prog_id, tcs->id); 1292 if (tes && tes->id > 0) 1293 glAttachShader(prog_id, tes->id); 1294 1295 if (gs) { 1296 if (gs->id > 0) 1297 glAttachShader(prog_id, gs->id); 1298 set_stream_out_varyings(prog_id, &gs->sel->sinfo); 1299 } else if (tes) 1300 set_stream_out_varyings(prog_id, &tes->sel->sinfo); 1301 else 1302 set_stream_out_varyings(prog_id, &vs->sel->sinfo); 1303 glAttachShader(prog_id, fs->id); 1304 1305 if (fs->sel->sinfo.num_outputs > 1) { 1306 if (util_blend_state_is_dual(&ctx->sub->blend_state, 0)) { 1307 glBindFragDataLocationIndexed(prog_id, 0, 0, "fsout_c0"); 1308 glBindFragDataLocationIndexed(prog_id, 0, 1, "fsout_c1"); 1309 sprog->dual_src_linked = true; 1310 } else { 1311 glBindFragDataLocationIndexed(prog_id, 0, 0, "fsout_c0"); 1312 glBindFragDataLocationIndexed(prog_id, 1, 0, "fsout_c1"); 1313 sprog->dual_src_linked = false; 1314 } 1315 } else 1316 sprog->dual_src_linked = false; 1317 1318 if (has_feature(feat_gles31_vertex_attrib_binding)) { 1319 uint32_t mask = vs->sel->sinfo.attrib_input_mask; 1320 while (mask) { 1321 i = u_bit_scan(&mask); 1322 snprintf(name, 32, "in_%d", i); 1323 glBindAttribLocation(prog_id, i, name); 1324 } 1325 } 1326 1327 glLinkProgram(prog_id); 1328 1329 glGetProgramiv(prog_id, GL_LINK_STATUS, &lret); 1330 if (lret == GL_FALSE) { 1331 char infolog[65536]; 1332 int len; 1333 glGetProgramInfoLog(prog_id, 65536, &len, infolog); 1334 fprintf(stderr,"got error linking\n%s\n", infolog); 1335 /* dump shaders */ 1336 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SHADER, 0); 1337 fprintf(stderr,"vert shader: %d GLSL\n%s\n", vs->id, vs->glsl_prog); 1338 if (gs) 1339 fprintf(stderr,"geom shader: %d GLSL\n%s\n", gs->id, gs->glsl_prog); 1340 fprintf(stderr,"frag shader: %d GLSL\n%s\n", fs->id, fs->glsl_prog); 1341 glDeleteProgram(prog_id); 1342 free(sprog); 1343 return NULL; 1344 } 1345 1346 sprog->ss[PIPE_SHADER_VERTEX] = vs; 1347 sprog->ss[PIPE_SHADER_FRAGMENT] = fs; 1348 sprog->ss[PIPE_SHADER_GEOMETRY] = gs; 1349 sprog->ss[PIPE_SHADER_TESS_CTRL] = tcs; 1350 sprog->ss[PIPE_SHADER_TESS_EVAL] = tes; 1351 1352 list_add(&sprog->sl[PIPE_SHADER_VERTEX], &vs->programs); 1353 list_add(&sprog->sl[PIPE_SHADER_FRAGMENT], &fs->programs); 1354 if (gs) 1355 list_add(&sprog->sl[PIPE_SHADER_GEOMETRY], &gs->programs); 1356 if (tcs) 1357 list_add(&sprog->sl[PIPE_SHADER_TESS_CTRL], &tcs->programs); 1358 if (tes) 1359 list_add(&sprog->sl[PIPE_SHADER_TESS_EVAL], &tes->programs); 1360 1361 last_shader = tes ? PIPE_SHADER_TESS_EVAL : (gs ? PIPE_SHADER_GEOMETRY : PIPE_SHADER_FRAGMENT); 1362 sprog->id = prog_id; 1363 1364 list_addtail(&sprog->head, &ctx->sub->programs); 1365 1366 if (fs->key.pstipple_tex) 1367 sprog->fs_stipple_loc = glGetUniformLocation(prog_id, "pstipple_sampler"); 1368 else 1369 sprog->fs_stipple_loc = -1; 1370 sprog->vs_ws_adjust_loc = glGetUniformLocation(prog_id, "winsys_adjust_y"); 1371 for (id = PIPE_SHADER_VERTEX; id <= last_shader; id++) { 1372 if (!sprog->ss[id]) 1373 continue; 1374 1375 bind_sampler_locs(sprog, id); 1376 bind_const_locs(sprog, id); 1377 bind_ubo_locs(sprog, id); 1378 bind_image_locs(sprog, id); 1379 bind_ssbo_locs(sprog, id); 1380 } 1381 1382 if (!has_feature(feat_gles31_vertex_attrib_binding)) { 1383 if (vs->sel->sinfo.num_inputs) { 1384 sprog->attrib_locs = calloc(vs->sel->sinfo.num_inputs, sizeof(uint32_t)); 1385 if (sprog->attrib_locs) { 1386 for (i = 0; i < vs->sel->sinfo.num_inputs; i++) { 1387 snprintf(name, 32, "in_%d", i); 1388 sprog->attrib_locs[i] = glGetAttribLocation(prog_id, name); 1389 } 1390 } 1391 } else 1392 sprog->attrib_locs = NULL; 1393 } 1394 1395 if (vs->sel->sinfo.num_ucp) { 1396 for (i = 0; i < vs->sel->sinfo.num_ucp; i++) { 1397 snprintf(name, 32, "clipp[%d]", i); 1398 sprog->clip_locs[i] = glGetUniformLocation(prog_id, name); 1399 } 1400 } 1401 return sprog; 1402 } 1403 1404 static struct vrend_linked_shader_program *lookup_cs_shader_program(struct vrend_context *ctx, 1405 GLuint cs_id) 1406 { 1407 struct vrend_linked_shader_program *ent; 1408 LIST_FOR_EACH_ENTRY(ent, &ctx->sub->programs, head) { 1409 if (!ent->ss[PIPE_SHADER_COMPUTE]) 1410 continue; 1411 if (ent->ss[PIPE_SHADER_COMPUTE]->id == cs_id) 1412 return ent; 1413 } 1414 return NULL; 1415 } 1416 1417 static struct vrend_linked_shader_program *lookup_shader_program(struct vrend_context *ctx, 1418 GLuint vs_id, 1419 GLuint fs_id, 1420 GLuint gs_id, 1421 GLuint tcs_id, 1422 GLuint tes_id, 1423 bool dual_src) 1424 { 1425 struct vrend_linked_shader_program *ent; 1426 LIST_FOR_EACH_ENTRY(ent, &ctx->sub->programs, head) { 1427 if (ent->dual_src_linked != dual_src) 1428 continue; 1429 if (ent->ss[PIPE_SHADER_COMPUTE]) 1430 continue; 1431 if (ent->ss[PIPE_SHADER_VERTEX]->id != vs_id) 1432 continue; 1433 if (ent->ss[PIPE_SHADER_FRAGMENT]->id != fs_id) 1434 continue; 1435 if (ent->ss[PIPE_SHADER_GEOMETRY] && 1436 ent->ss[PIPE_SHADER_GEOMETRY]->id != gs_id) 1437 continue; 1438 if (ent->ss[PIPE_SHADER_TESS_CTRL] && 1439 ent->ss[PIPE_SHADER_TESS_CTRL]->id != tcs_id) 1440 continue; 1441 if (ent->ss[PIPE_SHADER_TESS_EVAL] && 1442 ent->ss[PIPE_SHADER_TESS_EVAL]->id != tes_id) 1443 continue; 1444 return ent; 1445 } 1446 return NULL; 1447 } 1448 1449 static void vrend_destroy_program(struct vrend_linked_shader_program *ent) 1450 { 1451 int i; 1452 glDeleteProgram(ent->id); 1453 list_del(&ent->head); 1454 1455 for (i = PIPE_SHADER_VERTEX; i <= PIPE_SHADER_COMPUTE; i++) { 1456 if (ent->ss[i]) 1457 list_del(&ent->sl[i]); 1458 free(ent->shadow_samp_mask_locs[i]); 1459 free(ent->shadow_samp_add_locs[i]); 1460 free(ent->samp_locs[i]); 1461 free(ent->ssbo_locs[i]); 1462 free(ent->img_locs[i]); 1463 free(ent->const_locs[i]); 1464 free(ent->ubo_locs[i]); 1465 } 1466 free(ent->attrib_locs); 1467 free(ent); 1468 } 1469 1470 static void vrend_free_programs(struct vrend_sub_context *sub) 1471 { 1472 struct vrend_linked_shader_program *ent, *tmp; 1473 1474 if (LIST_IS_EMPTY(&sub->programs)) 1475 return; 1476 1477 LIST_FOR_EACH_ENTRY_SAFE(ent, tmp, &sub->programs, head) { 1478 vrend_destroy_program(ent); 1479 } 1480 } 1481 1482 static void vrend_destroy_streamout_object(struct vrend_streamout_object *obj) 1483 { 1484 unsigned i; 1485 list_del(&obj->head); 1486 for (i = 0; i < obj->num_targets; i++) 1487 vrend_so_target_reference(&obj->so_targets[i], NULL); 1488 if (has_feature(feat_transform_feedback2)) 1489 glDeleteTransformFeedbacks(1, &obj->id); 1490 FREE(obj); 1491 } 1492 1493 int vrend_create_surface(struct vrend_context *ctx, 1494 uint32_t handle, 1495 uint32_t res_handle, uint32_t format, 1496 uint32_t val0, uint32_t val1) 1497 { 1498 struct vrend_surface *surf; 1499 struct vrend_resource *res; 1500 uint32_t ret_handle; 1501 1502 if (format >= PIPE_FORMAT_COUNT) { 1503 return EINVAL; 1504 } 1505 1506 res = vrend_renderer_ctx_res_lookup(ctx, res_handle); 1507 if (!res) { 1508 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); 1509 return EINVAL; 1510 } 1511 1512 surf = CALLOC_STRUCT(vrend_surface); 1513 if (!surf) 1514 return ENOMEM; 1515 1516 surf->res_handle = res_handle; 1517 surf->format = format; 1518 surf->val0 = val0; 1519 surf->val1 = val1; 1520 surf->id = res->id; 1521 1522 if (has_feature(feat_texture_view) && !res->is_buffer) { 1523 /* We don't need texture views for buffer objects. 1524 * Otherwise we only need a texture view if the 1525 * a) formats differ between the surface and base texture 1526 * b) we need to map a sub range > 1 layer to a surface, 1527 * GL can make a single layer fine without a view, and it 1528 * can map the whole texure fine. In those cases we don't 1529 * create a texture view. 1530 */ 1531 int first_layer = surf->val1 & 0xffff; 1532 int last_layer = (surf->val1 >> 16) & 0xffff; 1533 1534 if ((first_layer != last_layer && 1535 (first_layer != 0 || (last_layer != (int)util_max_layer(&res->base, surf->val0)))) || 1536 surf->format != res->base.format) { 1537 GLenum internalformat = tex_conv_table[surf->format].internalformat; 1538 glGenTextures(1, &surf->id); 1539 glTextureView(surf->id, res->target, res->id, internalformat, 1540 0, res->base.last_level + 1, 1541 first_layer, last_layer - first_layer + 1); 1542 } 1543 } 1544 1545 pipe_reference_init(&surf->reference, 1); 1546 1547 vrend_resource_reference(&surf->texture, res); 1548 1549 ret_handle = vrend_renderer_object_insert(ctx, surf, sizeof(*surf), handle, VIRGL_OBJECT_SURFACE); 1550 if (ret_handle == 0) { 1551 FREE(surf); 1552 return ENOMEM; 1553 } 1554 return 0; 1555 } 1556 1557 static void vrend_destroy_surface_object(void *obj_ptr) 1558 { 1559 struct vrend_surface *surface = obj_ptr; 1560 1561 vrend_surface_reference(&surface, NULL); 1562 } 1563 1564 static void vrend_destroy_sampler_view_object(void *obj_ptr) 1565 { 1566 struct vrend_sampler_view *samp = obj_ptr; 1567 1568 vrend_sampler_view_reference(&samp, NULL); 1569 } 1570 1571 static void vrend_destroy_so_target_object(void *obj_ptr) 1572 { 1573 struct vrend_so_target *target = obj_ptr; 1574 struct vrend_sub_context *sub_ctx = target->sub_ctx; 1575 struct vrend_streamout_object *obj, *tmp; 1576 bool found; 1577 unsigned i; 1578 1579 LIST_FOR_EACH_ENTRY_SAFE(obj, tmp, &sub_ctx->streamout_list, head) { 1580 found = false; 1581 for (i = 0; i < obj->num_targets; i++) { 1582 if (obj->so_targets[i] == target) { 1583 found = true; 1584 break; 1585 } 1586 } 1587 if (found) { 1588 if (obj == sub_ctx->current_so) 1589 sub_ctx->current_so = NULL; 1590 if (obj->xfb_state == XFB_STATE_PAUSED) { 1591 if (has_feature(feat_transform_feedback2)) 1592 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, obj->id); 1593 glEndTransformFeedback(); 1594 if (sub_ctx->current_so && has_feature(feat_transform_feedback2)) 1595 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, sub_ctx->current_so->id); 1596 } 1597 vrend_destroy_streamout_object(obj); 1598 } 1599 } 1600 1601 vrend_so_target_reference(&target, NULL); 1602 } 1603 1604 static void vrend_destroy_vertex_elements_object(void *obj_ptr) 1605 { 1606 struct vrend_vertex_element_array *v = obj_ptr; 1607 1608 if (has_feature(feat_gles31_vertex_attrib_binding)) { 1609 glDeleteVertexArrays(1, &v->id); 1610 } 1611 FREE(v); 1612 } 1613 1614 static void vrend_destroy_sampler_state_object(void *obj_ptr) 1615 { 1616 struct vrend_sampler_state *state = obj_ptr; 1617 1618 if (has_feature(feat_samplers)) 1619 glDeleteSamplers(1, &state->id); 1620 FREE(state); 1621 } 1622 1623 static GLuint convert_wrap(int wrap) 1624 { 1625 switch(wrap){ 1626 case PIPE_TEX_WRAP_REPEAT: return GL_REPEAT; 1627 case PIPE_TEX_WRAP_CLAMP: if (vrend_state.use_core_profile == false) return GL_CLAMP; else return GL_CLAMP_TO_EDGE; 1628 1629 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE; 1630 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return GL_CLAMP_TO_BORDER; 1631 1632 case PIPE_TEX_WRAP_MIRROR_REPEAT: return GL_MIRRORED_REPEAT; 1633 case PIPE_TEX_WRAP_MIRROR_CLAMP: return GL_MIRROR_CLAMP_EXT; 1634 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: return GL_MIRROR_CLAMP_TO_EDGE_EXT; 1635 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: return GL_MIRROR_CLAMP_TO_BORDER_EXT; 1636 default: 1637 assert(0); 1638 return -1; 1639 } 1640 } 1641 1642 static inline GLenum convert_mag_filter(unsigned int filter) 1643 { 1644 if (filter == PIPE_TEX_FILTER_NEAREST) 1645 return GL_NEAREST; 1646 return GL_LINEAR; 1647 } 1648 1649 static inline GLenum convert_min_filter(unsigned int filter, unsigned int mip_filter) 1650 { 1651 if (mip_filter == PIPE_TEX_MIPFILTER_NONE) 1652 return convert_mag_filter(filter); 1653 else if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { 1654 if (filter == PIPE_TEX_FILTER_NEAREST) 1655 return GL_NEAREST_MIPMAP_LINEAR; 1656 else 1657 return GL_LINEAR_MIPMAP_LINEAR; 1658 } else if (mip_filter == PIPE_TEX_MIPFILTER_NEAREST) { 1659 if (filter == PIPE_TEX_FILTER_NEAREST) 1660 return GL_NEAREST_MIPMAP_NEAREST; 1661 else 1662 return GL_LINEAR_MIPMAP_NEAREST; 1663 } 1664 assert(0); 1665 return 0; 1666 } 1667 1668 int vrend_create_sampler_state(struct vrend_context *ctx, 1669 uint32_t handle, 1670 struct pipe_sampler_state *templ) 1671 { 1672 struct vrend_sampler_state *state = CALLOC_STRUCT(vrend_sampler_state); 1673 int ret_handle; 1674 1675 if (!state) 1676 return ENOMEM; 1677 1678 state->base = *templ; 1679 1680 if (has_feature(feat_samplers)) { 1681 glGenSamplers(1, &state->id); 1682 1683 glSamplerParameteri(state->id, GL_TEXTURE_WRAP_S, convert_wrap(templ->wrap_s)); 1684 glSamplerParameteri(state->id, GL_TEXTURE_WRAP_T, convert_wrap(templ->wrap_t)); 1685 glSamplerParameteri(state->id, GL_TEXTURE_WRAP_R, convert_wrap(templ->wrap_r)); 1686 glSamplerParameterf(state->id, GL_TEXTURE_MIN_FILTER, convert_min_filter(templ->min_img_filter, templ->min_mip_filter)); 1687 glSamplerParameterf(state->id, GL_TEXTURE_MAG_FILTER, convert_mag_filter(templ->mag_img_filter)); 1688 glSamplerParameterf(state->id, GL_TEXTURE_MIN_LOD, templ->min_lod); 1689 glSamplerParameterf(state->id, GL_TEXTURE_MAX_LOD, templ->max_lod); 1690 glSamplerParameteri(state->id, GL_TEXTURE_COMPARE_MODE, templ->compare_mode ? GL_COMPARE_R_TO_TEXTURE : GL_NONE); 1691 glSamplerParameteri(state->id, GL_TEXTURE_COMPARE_FUNC, GL_NEVER + templ->compare_func); 1692 if (vrend_state.use_gles) { 1693 if (templ->lod_bias != 0.0f) { 1694 report_gles_warn(ctx, GLES_WARN_LOD_BIAS, 0); 1695 } 1696 } else { 1697 glSamplerParameteri(state->id, GL_TEXTURE_CUBE_MAP_SEAMLESS, templ->seamless_cube_map); 1698 glSamplerParameterf(state->id, GL_TEXTURE_LOD_BIAS, templ->lod_bias); 1699 } 1700 1701 glSamplerParameterIuiv(state->id, GL_TEXTURE_BORDER_COLOR, templ->border_color.ui); 1702 } 1703 ret_handle = vrend_renderer_object_insert(ctx, state, sizeof(struct vrend_sampler_state), handle, 1704 VIRGL_OBJECT_SAMPLER_STATE); 1705 if (!ret_handle) { 1706 if (has_feature(feat_samplers)) 1707 glDeleteSamplers(1, &state->id); 1708 FREE(state); 1709 return ENOMEM; 1710 } 1711 return 0; 1712 } 1713 1714 static inline GLenum to_gl_swizzle(int swizzle) 1715 { 1716 switch (swizzle) { 1717 case PIPE_SWIZZLE_RED: return GL_RED; 1718 case PIPE_SWIZZLE_GREEN: return GL_GREEN; 1719 case PIPE_SWIZZLE_BLUE: return GL_BLUE; 1720 case PIPE_SWIZZLE_ALPHA: return GL_ALPHA; 1721 case PIPE_SWIZZLE_ZERO: return GL_ZERO; 1722 case PIPE_SWIZZLE_ONE: return GL_ONE; 1723 default: 1724 assert(0); 1725 return 0; 1726 } 1727 } 1728 1729 int vrend_create_sampler_view(struct vrend_context *ctx, 1730 uint32_t handle, 1731 uint32_t res_handle, uint32_t format, 1732 uint32_t val0, uint32_t val1, uint32_t swizzle_packed) 1733 { 1734 struct vrend_sampler_view *view; 1735 struct vrend_resource *res; 1736 int ret_handle; 1737 uint8_t swizzle[4]; 1738 1739 res = vrend_renderer_ctx_res_lookup(ctx, res_handle); 1740 if (!res) { 1741 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); 1742 return EINVAL; 1743 } 1744 1745 view = CALLOC_STRUCT(vrend_sampler_view); 1746 if (!view) 1747 return ENOMEM; 1748 1749 pipe_reference_init(&view->reference, 1); 1750 view->format = format & 0xffffff; 1751 view->target = tgsitargettogltarget((format >> 24) & 0xff, res->base.nr_samples); 1752 view->val0 = val0; 1753 view->val1 = val1; 1754 view->cur_base = -1; 1755 view->cur_max = 10000; 1756 1757 swizzle[0] = swizzle_packed & 0x7; 1758 swizzle[1] = (swizzle_packed >> 3) & 0x7; 1759 swizzle[2] = (swizzle_packed >> 6) & 0x7; 1760 swizzle[3] = (swizzle_packed >> 9) & 0x7; 1761 1762 vrend_resource_reference(&view->texture, res); 1763 1764 view->id = view->texture->id; 1765 if (!view->target) 1766 view->target = view->texture->target; 1767 1768 if (has_feature(feat_texture_view) && !view->texture->is_buffer) { 1769 enum pipe_format format; 1770 bool needs_view = false; 1771 1772 /* 1773 * Need to use a texture view if the gallium 1774 * view target is different than the underlying 1775 * texture target. 1776 */ 1777 if (view->target != view->texture->target) 1778 needs_view = true; 1779 1780 /* 1781 * If the formats are different and this isn't 1782 * a DS texture a view is required. 1783 * DS are special as they use different gallium 1784 * formats for DS views into a combined resource. 1785 * GL texture views can't be use for this, stencil 1786 * texturing is used instead. For DS formats 1787 * aways program the underlying DS format as a 1788 * view could be required for layers. 1789 */ 1790 format = view->format; 1791 if (util_format_is_depth_or_stencil(view->texture->base.format)) 1792 format = view->texture->base.format; 1793 else if (view->format != view->texture->base.format) 1794 needs_view = true; 1795 if (needs_view) { 1796 glGenTextures(1, &view->id); 1797 GLenum internalformat = tex_conv_table[format].internalformat; 1798 unsigned base_layer = view->val0 & 0xffff; 1799 unsigned max_layer = (view->val0 >> 16) & 0xffff; 1800 view->cur_base = view->val1 & 0xff; 1801 view->cur_max = (view->val1 >> 8) & 0xff; 1802 glTextureView(view->id, view->target, view->texture->id, internalformat, 1803 view->cur_base, (view->cur_max - view->cur_base) + 1, 1804 base_layer, max_layer - base_layer + 1); 1805 } 1806 } 1807 view->srgb_decode = GL_DECODE_EXT; 1808 if (view->format != view->texture->base.format) { 1809 if (util_format_is_srgb(view->texture->base.format) && 1810 !util_format_is_srgb(view->format)) 1811 view->srgb_decode = GL_SKIP_DECODE_EXT; 1812 } 1813 1814 if (!(util_format_has_alpha(view->format) || util_format_is_depth_or_stencil(view->format))) { 1815 if (swizzle[0] == PIPE_SWIZZLE_ALPHA) 1816 swizzle[0] = PIPE_SWIZZLE_ONE; 1817 if (swizzle[1] == PIPE_SWIZZLE_ALPHA) 1818 swizzle[1] = PIPE_SWIZZLE_ONE; 1819 if (swizzle[2] == PIPE_SWIZZLE_ALPHA) 1820 swizzle[2] = PIPE_SWIZZLE_ONE; 1821 if (swizzle[3] == PIPE_SWIZZLE_ALPHA) 1822 swizzle[3] = PIPE_SWIZZLE_ONE; 1823 } 1824 1825 if (tex_conv_table[view->format].flags & VIRGL_BIND_NEED_SWIZZLE) { 1826 if (swizzle[0] <= PIPE_SWIZZLE_ALPHA) 1827 swizzle[0] = tex_conv_table[view->format].swizzle[swizzle[0]]; 1828 if (swizzle[1] <= PIPE_SWIZZLE_ALPHA) 1829 swizzle[1] = tex_conv_table[view->format].swizzle[swizzle[1]]; 1830 if (swizzle[2] <= PIPE_SWIZZLE_ALPHA) 1831 swizzle[2] = tex_conv_table[view->format].swizzle[swizzle[2]]; 1832 if (swizzle[3] <= PIPE_SWIZZLE_ALPHA) 1833 swizzle[3] = tex_conv_table[view->format].swizzle[swizzle[3]]; 1834 } 1835 1836 view->gl_swizzle_r = to_gl_swizzle(swizzle[0]); 1837 view->gl_swizzle_g = to_gl_swizzle(swizzle[1]); 1838 view->gl_swizzle_b = to_gl_swizzle(swizzle[2]); 1839 view->gl_swizzle_a = to_gl_swizzle(swizzle[3]); 1840 1841 view->cur_swizzle_r = view->cur_swizzle_g = 1842 view->cur_swizzle_b = view->cur_swizzle_a = -1; 1843 1844 ret_handle = vrend_renderer_object_insert(ctx, view, sizeof(*view), handle, VIRGL_OBJECT_SAMPLER_VIEW); 1845 if (ret_handle == 0) { 1846 FREE(view); 1847 return ENOMEM; 1848 } 1849 return 0; 1850 } 1851 1852 static void vrend_fb_bind_texture_id(struct vrend_resource *res, 1853 int id, 1854 int idx, 1855 uint32_t level, uint32_t layer) 1856 { 1857 const struct util_format_description *desc = util_format_description(res->base.format); 1858 GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + idx; 1859 1860 if (vrend_format_is_ds(res->base.format)) { 1861 if (util_format_has_stencil(desc)) { 1862 if (util_format_has_depth(desc)) 1863 attachment = GL_DEPTH_STENCIL_ATTACHMENT; 1864 else 1865 attachment = GL_STENCIL_ATTACHMENT; 1866 } else 1867 attachment = GL_DEPTH_ATTACHMENT; 1868 } 1869 1870 switch (res->target) { 1871 case GL_TEXTURE_1D_ARRAY: 1872 case GL_TEXTURE_2D_ARRAY: 1873 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1874 case GL_TEXTURE_CUBE_MAP_ARRAY: 1875 if (layer == 0xffffffff) 1876 glFramebufferTexture(GL_FRAMEBUFFER_EXT, attachment, 1877 id, level); 1878 else 1879 glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, attachment, 1880 id, level, layer); 1881 break; 1882 case GL_TEXTURE_3D: 1883 if (layer == 0xffffffff) 1884 glFramebufferTexture(GL_FRAMEBUFFER_EXT, attachment, 1885 id, level); 1886 else if (vrend_state.use_gles) 1887 glFramebufferTexture3DOES(GL_FRAMEBUFFER_EXT, attachment, 1888 res->target, id, level, layer); 1889 else 1890 glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, attachment, 1891 res->target, id, level, layer); 1892 break; 1893 case GL_TEXTURE_CUBE_MAP: 1894 if (layer == 0xffffffff) 1895 glFramebufferTexture(GL_FRAMEBUFFER_EXT, attachment, 1896 id, level); 1897 else 1898 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 1899 GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, id, level); 1900 break; 1901 case GL_TEXTURE_1D: 1902 glFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, attachment, 1903 res->target, id, level); 1904 break; 1905 case GL_TEXTURE_2D: 1906 default: 1907 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 1908 res->target, id, level); 1909 break; 1910 } 1911 1912 if (attachment == GL_DEPTH_ATTACHMENT) { 1913 switch (res->target) { 1914 case GL_TEXTURE_1D: 1915 glFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT, 1916 GL_TEXTURE_1D, 0, 0); 1917 break; 1918 case GL_TEXTURE_2D: 1919 default: 1920 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT, 1921 GL_TEXTURE_2D, 0, 0); 1922 break; 1923 } 1924 } 1925 } 1926 1927 void vrend_fb_bind_texture(struct vrend_resource *res, 1928 int idx, 1929 uint32_t level, uint32_t layer) 1930 { 1931 vrend_fb_bind_texture_id(res, res->id, idx, level, layer); 1932 } 1933 1934 static void vrend_hw_set_zsurf_texture(struct vrend_context *ctx) 1935 { 1936 struct vrend_surface *surf = ctx->sub->zsurf; 1937 1938 if (!surf) { 1939 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, 1940 GL_TEXTURE_2D, 0, 0); 1941 } else { 1942 uint32_t first_layer = surf->val1 & 0xffff; 1943 uint32_t last_layer = (surf->val1 >> 16) & 0xffff; 1944 1945 if (!surf->texture) 1946 return; 1947 1948 vrend_fb_bind_texture_id(surf->texture, surf->id, 0, surf->val0, 1949 first_layer != last_layer ? 0xffffffff : first_layer); 1950 } 1951 } 1952 1953 static void vrend_hw_set_color_surface(struct vrend_context *ctx, int index) 1954 { 1955 struct vrend_surface *surf = ctx->sub->surf[index]; 1956 1957 if (!surf) { 1958 GLenum attachment = GL_COLOR_ATTACHMENT0 + index; 1959 1960 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, 1961 GL_TEXTURE_2D, 0, 0); 1962 } else { 1963 uint32_t first_layer = ctx->sub->surf[index]->val1 & 0xffff; 1964 uint32_t last_layer = (ctx->sub->surf[index]->val1 >> 16) & 0xffff; 1965 1966 vrend_fb_bind_texture_id(surf->texture, surf->id, index, surf->val0, 1967 first_layer != last_layer ? 0xffffffff : first_layer); 1968 } 1969 } 1970 1971 static void vrend_hw_emit_framebuffer_state(struct vrend_context *ctx) 1972 { 1973 static const GLenum buffers[8] = { 1974 GL_COLOR_ATTACHMENT0_EXT, 1975 GL_COLOR_ATTACHMENT1_EXT, 1976 GL_COLOR_ATTACHMENT2_EXT, 1977 GL_COLOR_ATTACHMENT3_EXT, 1978 GL_COLOR_ATTACHMENT4_EXT, 1979 GL_COLOR_ATTACHMENT5_EXT, 1980 GL_COLOR_ATTACHMENT6_EXT, 1981 GL_COLOR_ATTACHMENT7_EXT, 1982 }; 1983 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->sub->fb_id); 1984 1985 if (ctx->sub->nr_cbufs == 0) { 1986 glReadBuffer(GL_NONE); 1987 if (!vrend_state.use_gles) { 1988 glDisable(GL_FRAMEBUFFER_SRGB_EXT); 1989 } 1990 } else if (!vrend_state.use_gles) { 1991 /* Do not enter this path on GLES as this is not needed. */ 1992 struct vrend_surface *surf = NULL; 1993 bool use_srgb = false; 1994 int i; 1995 for (i = 0; i < ctx->sub->nr_cbufs; i++) { 1996 if (ctx->sub->surf[i]) { 1997 surf = ctx->sub->surf[i]; 1998 if (util_format_is_srgb(surf->format)) { 1999 use_srgb = true; 2000 } 2001 } 2002 } 2003 if (use_srgb) { 2004 glEnable(GL_FRAMEBUFFER_SRGB_EXT); 2005 } else { 2006 glDisable(GL_FRAMEBUFFER_SRGB_EXT); 2007 } 2008 } 2009 glDrawBuffers(ctx->sub->nr_cbufs, buffers); 2010 } 2011 2012 void vrend_set_framebuffer_state(struct vrend_context *ctx, 2013 uint32_t nr_cbufs, uint32_t surf_handle[PIPE_MAX_COLOR_BUFS], 2014 uint32_t zsurf_handle) 2015 { 2016 struct vrend_surface *surf, *zsurf; 2017 int i; 2018 int old_num; 2019 GLenum status; 2020 GLint new_height = -1; 2021 bool new_ibf = false; 2022 2023 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->sub->fb_id); 2024 2025 if (zsurf_handle) { 2026 zsurf = vrend_object_lookup(ctx->sub->object_hash, zsurf_handle, VIRGL_OBJECT_SURFACE); 2027 if (!zsurf) { 2028 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SURFACE, zsurf_handle); 2029 return; 2030 } 2031 } else 2032 zsurf = NULL; 2033 2034 if (ctx->sub->zsurf != zsurf) { 2035 vrend_surface_reference(&ctx->sub->zsurf, zsurf); 2036 vrend_hw_set_zsurf_texture(ctx); 2037 } 2038 2039 old_num = ctx->sub->nr_cbufs; 2040 ctx->sub->nr_cbufs = nr_cbufs; 2041 ctx->sub->old_nr_cbufs = old_num; 2042 2043 for (i = 0; i < (int)nr_cbufs; i++) { 2044 if (surf_handle[i] != 0) { 2045 surf = vrend_object_lookup(ctx->sub->object_hash, surf_handle[i], VIRGL_OBJECT_SURFACE); 2046 if (!surf) { 2047 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SURFACE, surf_handle[i]); 2048 return; 2049 } 2050 } else 2051 surf = NULL; 2052 2053 if (ctx->sub->surf[i] != surf) { 2054 vrend_surface_reference(&ctx->sub->surf[i], surf); 2055 vrend_hw_set_color_surface(ctx, i); 2056 } 2057 } 2058 2059 if (old_num > ctx->sub->nr_cbufs) { 2060 for (i = ctx->sub->nr_cbufs; i < old_num; i++) { 2061 vrend_surface_reference(&ctx->sub->surf[i], NULL); 2062 vrend_hw_set_color_surface(ctx, i); 2063 } 2064 } 2065 2066 /* find a buffer to set fb_height from */ 2067 if (ctx->sub->nr_cbufs == 0 && !ctx->sub->zsurf) { 2068 new_height = 0; 2069 new_ibf = false; 2070 } else if (ctx->sub->nr_cbufs == 0) { 2071 new_height = u_minify(ctx->sub->zsurf->texture->base.height0, ctx->sub->zsurf->val0); 2072 new_ibf = ctx->sub->zsurf->texture->y_0_top ? true : false; 2073 } 2074 else { 2075 surf = NULL; 2076 for (i = 0; i < ctx->sub->nr_cbufs; i++) { 2077 if (ctx->sub->surf[i]) { 2078 surf = ctx->sub->surf[i]; 2079 break; 2080 } 2081 } 2082 if (surf == NULL) { 2083 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SURFACE, i); 2084 return; 2085 } 2086 new_height = u_minify(surf->texture->base.height0, surf->val0); 2087 new_ibf = surf->texture->y_0_top ? true : false; 2088 } 2089 2090 if (new_height != -1) { 2091 if (ctx->sub->fb_height != (uint32_t)new_height || ctx->sub->inverted_fbo_content != new_ibf) { 2092 ctx->sub->fb_height = new_height; 2093 ctx->sub->inverted_fbo_content = new_ibf; 2094 ctx->sub->scissor_state_dirty = (1 << 0); 2095 ctx->sub->viewport_state_dirty = (1 << 0); 2096 } 2097 } 2098 2099 vrend_hw_emit_framebuffer_state(ctx); 2100 2101 if (ctx->sub->nr_cbufs > 0 || ctx->sub->zsurf) { 2102 status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 2103 if (status != GL_FRAMEBUFFER_COMPLETE) 2104 fprintf(stderr,"failed to complete framebuffer 0x%x %s\n", status, ctx->debug_name); 2105 } 2106 ctx->sub->shader_dirty = true; 2107 } 2108 2109 void vrend_set_framebuffer_state_no_attach(UNUSED struct vrend_context *ctx, 2110 uint32_t width, uint32_t height, 2111 uint32_t layers, uint32_t samples) 2112 { 2113 if (has_feature(feat_fb_no_attach)) { 2114 glFramebufferParameteri(GL_FRAMEBUFFER, 2115 GL_FRAMEBUFFER_DEFAULT_WIDTH, width); 2116 glFramebufferParameteri(GL_FRAMEBUFFER, 2117 GL_FRAMEBUFFER_DEFAULT_HEIGHT, height); 2118 glFramebufferParameteri(GL_FRAMEBUFFER, 2119 GL_FRAMEBUFFER_DEFAULT_LAYERS, layers); 2120 glFramebufferParameteri(GL_FRAMEBUFFER, 2121 GL_FRAMEBUFFER_DEFAULT_SAMPLES, samples); 2122 } 2123 } 2124 2125 /* 2126 * if the viewport Y scale factor is > 0 then we are rendering to 2127 * an FBO already so don't need to invert rendering? 2128 */ 2129 void vrend_set_viewport_states(struct vrend_context *ctx, 2130 uint32_t start_slot, 2131 uint32_t num_viewports, 2132 const struct pipe_viewport_state *state) 2133 { 2134 /* convert back to glViewport */ 2135 GLint x, y; 2136 GLsizei width, height; 2137 GLclampd near_val, far_val; 2138 bool viewport_is_negative = (state[0].scale[1] < 0) ? true : false; 2139 uint i, idx; 2140 2141 if (num_viewports > PIPE_MAX_VIEWPORTS || 2142 start_slot > (PIPE_MAX_VIEWPORTS - num_viewports)) { 2143 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, num_viewports); 2144 return; 2145 } 2146 2147 for (i = 0; i < num_viewports; i++) { 2148 GLfloat abs_s1 = fabsf(state[i].scale[1]); 2149 2150 idx = start_slot + i; 2151 width = state[i].scale[0] * 2.0f; 2152 height = abs_s1 * 2.0f; 2153 x = state[i].translate[0] - state[i].scale[0]; 2154 y = state[i].translate[1] - state[i].scale[1]; 2155 2156 near_val = state[i].translate[2] - state[i].scale[2]; 2157 far_val = near_val + (state[i].scale[2] * 2.0); 2158 2159 if (ctx->sub->vps[idx].cur_x != x || 2160 ctx->sub->vps[idx].cur_y != y || 2161 ctx->sub->vps[idx].width != width || 2162 ctx->sub->vps[idx].height != height) { 2163 ctx->sub->viewport_state_dirty |= (1 << idx); 2164 ctx->sub->vps[idx].cur_x = x; 2165 ctx->sub->vps[idx].cur_y = y; 2166 ctx->sub->vps[idx].width = width; 2167 ctx->sub->vps[idx].height = height; 2168 } 2169 2170 if (idx == 0) { 2171 if (ctx->sub->viewport_is_negative != viewport_is_negative) 2172 ctx->sub->viewport_is_negative = viewport_is_negative; 2173 2174 ctx->sub->depth_scale = fabsf(far_val - near_val); 2175 ctx->sub->depth_transform = near_val; 2176 } 2177 2178 if (ctx->sub->vps[idx].near_val != near_val || 2179 ctx->sub->vps[idx].far_val != far_val) { 2180 ctx->sub->vps[idx].near_val = near_val; 2181 ctx->sub->vps[idx].far_val = far_val; 2182 2183 if (vrend_state.use_gles) { 2184 if (near_val < 0.0f || far_val < 0.0f || 2185 near_val > 1.0f || far_val > 1.0f || idx) { 2186 report_gles_warn(ctx, GLES_WARN_DEPTH_RANGE, 0); 2187 } 2188 2189 /* Best effort despite the warning, gles will clamp. */ 2190 glDepthRangef(ctx->sub->vps[idx].near_val, ctx->sub->vps[idx].far_val); 2191 } else if (idx && has_feature(feat_viewport_array)) 2192 glDepthRangeIndexed(idx, ctx->sub->vps[idx].near_val, ctx->sub->vps[idx].far_val); 2193 else 2194 glDepthRange(ctx->sub->vps[idx].near_val, ctx->sub->vps[idx].far_val); 2195 } 2196 } 2197 } 2198 2199 int vrend_create_vertex_elements_state(struct vrend_context *ctx, 2200 uint32_t handle, 2201 unsigned num_elements, 2202 const struct pipe_vertex_element *elements) 2203 { 2204 struct vrend_vertex_element_array *v; 2205 const struct util_format_description *desc; 2206 GLenum type; 2207 uint i; 2208 uint32_t ret_handle; 2209 2210 if (num_elements > PIPE_MAX_ATTRIBS) 2211 return EINVAL; 2212 2213 v = CALLOC_STRUCT(vrend_vertex_element_array); 2214 if (!v) 2215 return ENOMEM; 2216 2217 v->count = num_elements; 2218 for (i = 0; i < num_elements; i++) { 2219 memcpy(&v->elements[i].base, &elements[i], sizeof(struct pipe_vertex_element)); 2220 2221 desc = util_format_description(elements[i].src_format); 2222 if (!desc) { 2223 FREE(v); 2224 return EINVAL; 2225 } 2226 2227 type = GL_FALSE; 2228 if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) { 2229 if (desc->channel[0].size == 32) 2230 type = GL_FLOAT; 2231 else if (desc->channel[0].size == 64) 2232 type = GL_DOUBLE; 2233 else if (desc->channel[0].size == 16) 2234 type = GL_HALF_FLOAT; 2235 } else if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED && 2236 desc->channel[0].size == 8) 2237 type = GL_UNSIGNED_BYTE; 2238 else if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED && 2239 desc->channel[0].size == 8) 2240 type = GL_BYTE; 2241 else if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED && 2242 desc->channel[0].size == 16) 2243 type = GL_UNSIGNED_SHORT; 2244 else if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED && 2245 desc->channel[0].size == 16) 2246 type = GL_SHORT; 2247 else if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED && 2248 desc->channel[0].size == 32) 2249 type = GL_UNSIGNED_INT; 2250 else if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED && 2251 desc->channel[0].size == 32) 2252 type = GL_INT; 2253 else if (elements[i].src_format == PIPE_FORMAT_R10G10B10A2_SSCALED || 2254 elements[i].src_format == PIPE_FORMAT_R10G10B10A2_SNORM || 2255 elements[i].src_format == PIPE_FORMAT_B10G10R10A2_SNORM) 2256 type = GL_INT_2_10_10_10_REV; 2257 else if (elements[i].src_format == PIPE_FORMAT_R10G10B10A2_USCALED || 2258 elements[i].src_format == PIPE_FORMAT_R10G10B10A2_UNORM || 2259 elements[i].src_format == PIPE_FORMAT_B10G10R10A2_UNORM) 2260 type = GL_UNSIGNED_INT_2_10_10_10_REV; 2261 else if (elements[i].src_format == PIPE_FORMAT_R11G11B10_FLOAT) 2262 type = GL_UNSIGNED_INT_10F_11F_11F_REV; 2263 2264 if (type == GL_FALSE) { 2265 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_VERTEX_FORMAT, elements[i].src_format); 2266 FREE(v); 2267 return EINVAL; 2268 } 2269 2270 v->elements[i].type = type; 2271 if (desc->channel[0].normalized) 2272 v->elements[i].norm = GL_TRUE; 2273 if (desc->nr_channels == 4 && desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_Z) 2274 v->elements[i].nr_chan = GL_BGRA; 2275 else if (elements[i].src_format == PIPE_FORMAT_R11G11B10_FLOAT) 2276 v->elements[i].nr_chan = 3; 2277 else 2278 v->elements[i].nr_chan = desc->nr_channels; 2279 } 2280 2281 if (has_feature(feat_gles31_vertex_attrib_binding)) { 2282 glGenVertexArrays(1, &v->id); 2283 glBindVertexArray(v->id); 2284 for (i = 0; i < num_elements; i++) { 2285 struct vrend_vertex_element *ve = &v->elements[i]; 2286 2287 if (util_format_is_pure_integer(ve->base.src_format)) 2288 glVertexAttribIFormat(i, ve->nr_chan, ve->type, ve->base.src_offset); 2289 else 2290 glVertexAttribFormat(i, ve->nr_chan, ve->type, ve->norm, ve->base.src_offset); 2291 glVertexAttribBinding(i, ve->base.vertex_buffer_index); 2292 glVertexBindingDivisor(i, ve->base.instance_divisor); 2293 glEnableVertexAttribArray(i); 2294 } 2295 } 2296 ret_handle = vrend_renderer_object_insert(ctx, v, sizeof(struct vrend_vertex_element), handle, 2297 VIRGL_OBJECT_VERTEX_ELEMENTS); 2298 if (!ret_handle) { 2299 FREE(v); 2300 return ENOMEM; 2301 } 2302 return 0; 2303 } 2304 2305 void vrend_bind_vertex_elements_state(struct vrend_context *ctx, 2306 uint32_t handle) 2307 { 2308 struct vrend_vertex_element_array *v; 2309 2310 if (!handle) { 2311 ctx->sub->ve = NULL; 2312 return; 2313 } 2314 v = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_VERTEX_ELEMENTS); 2315 if (!v) { 2316 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); 2317 return; 2318 } 2319 2320 if (ctx->sub->ve != v) 2321 ctx->sub->vbo_dirty = true; 2322 ctx->sub->ve = v; 2323 } 2324 2325 void vrend_set_constants(struct vrend_context *ctx, 2326 uint32_t shader, 2327 UNUSED uint32_t index, 2328 uint32_t num_constant, 2329 float *data) 2330 { 2331 struct vrend_constants *consts; 2332 uint i; 2333 2334 consts = &ctx->sub->consts[shader]; 2335 ctx->sub->const_dirty[shader] = true; 2336 2337 consts->consts = realloc(consts->consts, num_constant * sizeof(float)); 2338 if (!consts->consts) 2339 return; 2340 2341 consts->num_consts = num_constant; 2342 for (i = 0; i < num_constant; i++) 2343 consts->consts[i] = ((unsigned int *)data)[i]; 2344 } 2345 2346 void vrend_set_uniform_buffer(struct vrend_context *ctx, 2347 uint32_t shader, 2348 uint32_t index, 2349 uint32_t offset, 2350 uint32_t length, 2351 uint32_t res_handle) 2352 { 2353 struct vrend_resource *res; 2354 2355 if (!has_feature(feat_ubo)) 2356 return; 2357 2358 if (res_handle) { 2359 res = vrend_renderer_ctx_res_lookup(ctx, res_handle); 2360 2361 if (!res) { 2362 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); 2363 return; 2364 } 2365 vrend_resource_reference((struct vrend_resource **)&ctx->sub->cbs[shader][index].buffer, res); 2366 ctx->sub->cbs[shader][index].buffer_offset = offset; 2367 ctx->sub->cbs[shader][index].buffer_size = length; 2368 2369 ctx->sub->const_bufs_used_mask[shader] |= (1 << index); 2370 } else { 2371 vrend_resource_reference((struct vrend_resource **)&ctx->sub->cbs[shader][index].buffer, NULL); 2372 ctx->sub->cbs[shader][index].buffer_offset = 0; 2373 ctx->sub->cbs[shader][index].buffer_size = 0; 2374 ctx->sub->const_bufs_used_mask[shader] &= ~(1 << index); 2375 } 2376 } 2377 2378 void vrend_set_index_buffer(struct vrend_context *ctx, 2379 uint32_t res_handle, 2380 uint32_t index_size, 2381 uint32_t offset) 2382 { 2383 struct vrend_resource *res; 2384 2385 ctx->sub->ib.index_size = index_size; 2386 ctx->sub->ib.offset = offset; 2387 if (res_handle) { 2388 if (ctx->sub->index_buffer_res_id != res_handle) { 2389 res = vrend_renderer_ctx_res_lookup(ctx, res_handle); 2390 if (!res) { 2391 vrend_resource_reference((struct vrend_resource **)&ctx->sub->ib.buffer, NULL); 2392 ctx->sub->index_buffer_res_id = 0; 2393 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); 2394 return; 2395 } 2396 vrend_resource_reference((struct vrend_resource **)&ctx->sub->ib.buffer, res); 2397 ctx->sub->index_buffer_res_id = res_handle; 2398 } 2399 } else { 2400 vrend_resource_reference((struct vrend_resource **)&ctx->sub->ib.buffer, NULL); 2401 ctx->sub->index_buffer_res_id = 0; 2402 } 2403 } 2404 2405 void vrend_set_single_vbo(struct vrend_context *ctx, 2406 int index, 2407 uint32_t stride, 2408 uint32_t buffer_offset, 2409 uint32_t res_handle) 2410 { 2411 struct vrend_resource *res; 2412 2413 if (ctx->sub->vbo[index].stride != stride || 2414 ctx->sub->vbo[index].buffer_offset != buffer_offset || 2415 ctx->sub->vbo_res_ids[index] != res_handle) 2416 ctx->sub->vbo_dirty = true; 2417 2418 ctx->sub->vbo[index].stride = stride; 2419 ctx->sub->vbo[index].buffer_offset = buffer_offset; 2420 2421 if (res_handle == 0) { 2422 vrend_resource_reference((struct vrend_resource **)&ctx->sub->vbo[index].buffer, NULL); 2423 ctx->sub->vbo_res_ids[index] = 0; 2424 } else if (ctx->sub->vbo_res_ids[index] != res_handle) { 2425 res = vrend_renderer_ctx_res_lookup(ctx, res_handle); 2426 if (!res) { 2427 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); 2428 ctx->sub->vbo_res_ids[index] = 0; 2429 return; 2430 } 2431 vrend_resource_reference((struct vrend_resource **)&ctx->sub->vbo[index].buffer, res); 2432 ctx->sub->vbo_res_ids[index] = res_handle; 2433 } 2434 } 2435 2436 void vrend_set_num_vbo(struct vrend_context *ctx, 2437 int num_vbo) 2438 { 2439 int old_num = ctx->sub->num_vbos; 2440 int i; 2441 2442 ctx->sub->num_vbos = num_vbo; 2443 ctx->sub->old_num_vbos = old_num; 2444 2445 if (old_num != num_vbo) 2446 ctx->sub->vbo_dirty = true; 2447 2448 for (i = num_vbo; i < old_num; i++) { 2449 vrend_resource_reference((struct vrend_resource **)&ctx->sub->vbo[i].buffer, NULL); 2450 ctx->sub->vbo_res_ids[i] = 0; 2451 } 2452 2453 } 2454 2455 void vrend_set_single_sampler_view(struct vrend_context *ctx, 2456 uint32_t shader_type, 2457 uint32_t index, 2458 uint32_t handle) 2459 { 2460 struct vrend_sampler_view *view = NULL; 2461 struct vrend_texture *tex; 2462 2463 if (handle) { 2464 view = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_SAMPLER_VIEW); 2465 if (!view) { 2466 ctx->sub->views[shader_type].views[index] = NULL; 2467 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); 2468 return; 2469 } 2470 if (ctx->sub->views[shader_type].views[index] == view) { 2471 return; 2472 } 2473 /* we should have a reference to this texture taken at create time */ 2474 tex = (struct vrend_texture *)view->texture; 2475 if (!tex) { 2476 return; 2477 } 2478 if (!view->texture->is_buffer) { 2479 glBindTexture(view->target, view->id); 2480 2481 if (util_format_is_depth_or_stencil(view->format)) { 2482 if (vrend_state.use_core_profile == false) { 2483 /* setting depth texture mode is deprecated in core profile */ 2484 if (view->depth_texture_mode != GL_RED) { 2485 glTexParameteri(view->texture->target, GL_DEPTH_TEXTURE_MODE, GL_RED); 2486 view->depth_texture_mode = GL_RED; 2487 } 2488 } 2489 if (has_feature(feat_stencil_texturing)) { 2490 const struct util_format_description *desc = util_format_description(view->format); 2491 if (!util_format_has_depth(desc)) { 2492 glTexParameteri(view->texture->target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); 2493 } else { 2494 glTexParameteri(view->texture->target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT); 2495 } 2496 } 2497 } 2498 2499 if (view->cur_base != (view->val1 & 0xff)) { 2500 view->cur_base = view->val1 & 0xff; 2501 glTexParameteri(view->texture->target, GL_TEXTURE_BASE_LEVEL, view->cur_base); 2502 } 2503 if (view->cur_max != ((view->val1 >> 8) & 0xff)) { 2504 view->cur_max = (view->val1 >> 8) & 0xff; 2505 glTexParameteri(view->texture->target, GL_TEXTURE_MAX_LEVEL, view->cur_max); 2506 } 2507 if (view->cur_swizzle_r != view->gl_swizzle_r) { 2508 glTexParameteri(view->texture->target, GL_TEXTURE_SWIZZLE_R, view->gl_swizzle_r); 2509 view->cur_swizzle_r = view->gl_swizzle_r; 2510 } 2511 if (view->cur_swizzle_g != view->gl_swizzle_g) { 2512 glTexParameteri(view->texture->target, GL_TEXTURE_SWIZZLE_G, view->gl_swizzle_g); 2513 view->cur_swizzle_g = view->gl_swizzle_g; 2514 } 2515 if (view->cur_swizzle_b != view->gl_swizzle_b) { 2516 glTexParameteri(view->texture->target, GL_TEXTURE_SWIZZLE_B, view->gl_swizzle_b); 2517 view->cur_swizzle_b = view->gl_swizzle_b; 2518 } 2519 if (view->cur_swizzle_a != view->gl_swizzle_a) { 2520 glTexParameteri(view->texture->target, GL_TEXTURE_SWIZZLE_A, view->gl_swizzle_a); 2521 view->cur_swizzle_a = view->gl_swizzle_a; 2522 } 2523 if (view->cur_srgb_decode != view->srgb_decode && util_format_is_srgb(view->format)) { 2524 if (has_feature(feat_samplers)) 2525 ctx->sub->sampler_state_dirty = true; 2526 else if (has_feature(feat_texture_srgb_decode)) { 2527 glTexParameteri(view->texture->target, GL_TEXTURE_SRGB_DECODE_EXT, 2528 view->srgb_decode); 2529 view->cur_srgb_decode = view->srgb_decode; 2530 } 2531 } 2532 } else { 2533 GLenum internalformat; 2534 2535 if (!view->texture->tbo_tex_id) 2536 glGenTextures(1, &view->texture->tbo_tex_id); 2537 2538 glBindTexture(GL_TEXTURE_BUFFER, view->texture->tbo_tex_id); 2539 internalformat = tex_conv_table[view->format].internalformat; 2540 if (has_feature(feat_texture_buffer_range)) { 2541 unsigned offset = view->val0; 2542 unsigned size = view->val1 - view->val0 + 1; 2543 int blsize = util_format_get_blocksize(view->format); 2544 2545 offset *= blsize; 2546 size *= blsize; 2547 glTexBufferRange(GL_TEXTURE_BUFFER, internalformat, view->texture->id, offset, size); 2548 } else 2549 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, view->texture->id); 2550 } 2551 } 2552 2553 vrend_sampler_view_reference(&ctx->sub->views[shader_type].views[index], view); 2554 } 2555 2556 void vrend_set_num_sampler_views(struct vrend_context *ctx, 2557 uint32_t shader_type, 2558 uint32_t start_slot, 2559 int num_sampler_views) 2560 { 2561 int last_slot = start_slot + num_sampler_views; 2562 int i; 2563 2564 for (i = last_slot; i < ctx->sub->views[shader_type].num_views; i++) 2565 vrend_sampler_view_reference(&ctx->sub->views[shader_type].views[i], NULL); 2566 2567 ctx->sub->views[shader_type].num_views = last_slot; 2568 } 2569 2570 void vrend_set_single_image_view(struct vrend_context *ctx, 2571 uint32_t shader_type, 2572 int index, 2573 uint32_t format, uint32_t access, 2574 uint32_t layer_offset, uint32_t level_size, 2575 uint32_t handle) 2576 { 2577 struct vrend_image_view *iview = &ctx->sub->image_views[shader_type][index]; 2578 struct vrend_resource *res; 2579 2580 if (!has_feature(feat_images)) 2581 return; 2582 2583 if (handle) { 2584 res = vrend_renderer_ctx_res_lookup(ctx, handle); 2585 if (!res) { 2586 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, handle); 2587 return; 2588 } 2589 iview->texture = res; 2590 iview->format = tex_conv_table[format].internalformat; 2591 iview->access = access; 2592 iview->u.buf.offset = layer_offset; 2593 iview->u.buf.size = level_size; 2594 ctx->sub->images_used_mask[shader_type] |= (1 << index); 2595 } else { 2596 iview->texture = NULL; 2597 iview->format = 0; 2598 ctx->sub->images_used_mask[shader_type] &= ~(1 << index); 2599 } 2600 } 2601 2602 void vrend_set_single_ssbo(struct vrend_context *ctx, 2603 uint32_t shader_type, 2604 int index, 2605 uint32_t offset, uint32_t length, 2606 uint32_t handle) 2607 { 2608 struct vrend_ssbo *ssbo = &ctx->sub->ssbo[shader_type][index]; 2609 struct vrend_resource *res; 2610 2611 if (!has_feature(feat_ssbo)) 2612 return; 2613 2614 if (handle) { 2615 res = vrend_renderer_ctx_res_lookup(ctx, handle); 2616 if (!res) { 2617 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, handle); 2618 return; 2619 } 2620 ssbo->res = res; 2621 ssbo->buffer_offset = offset; 2622 ssbo->buffer_size = length; 2623 ctx->sub->ssbo_used_mask[shader_type] |= (1 << index); 2624 } else { 2625 ssbo->res = 0; 2626 ssbo->buffer_offset = 0; 2627 ssbo->buffer_size = 0; 2628 ctx->sub->ssbo_used_mask[shader_type] &= ~(1 << index); 2629 } 2630 } 2631 2632 void vrend_memory_barrier(UNUSED struct vrend_context *ctx, 2633 unsigned flags) 2634 { 2635 GLbitfield gl_barrier = 0; 2636 2637 if (!has_feature(feat_barrier)) 2638 return; 2639 2640 if ((flags & PIPE_BARRIER_ALL) == PIPE_BARRIER_ALL) 2641 gl_barrier = GL_ALL_BARRIER_BITS; 2642 else { 2643 if (flags & PIPE_BARRIER_VERTEX_BUFFER) 2644 gl_barrier |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT; 2645 if (flags & PIPE_BARRIER_INDEX_BUFFER) 2646 gl_barrier |= GL_ELEMENT_ARRAY_BARRIER_BIT; 2647 if (flags & PIPE_BARRIER_CONSTANT_BUFFER) 2648 gl_barrier |= GL_UNIFORM_BARRIER_BIT; 2649 if (flags & PIPE_BARRIER_TEXTURE) 2650 gl_barrier |= GL_TEXTURE_FETCH_BARRIER_BIT | GL_PIXEL_BUFFER_BARRIER_BIT; 2651 if (flags & PIPE_BARRIER_IMAGE) 2652 gl_barrier |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; 2653 if (flags & PIPE_BARRIER_INDIRECT_BUFFER) 2654 gl_barrier |= GL_COMMAND_BARRIER_BIT; 2655 if (flags & PIPE_BARRIER_MAPPED_BUFFER) 2656 gl_barrier |= GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT; 2657 if (flags & PIPE_BARRIER_FRAMEBUFFER) 2658 gl_barrier |= GL_FRAMEBUFFER_BARRIER_BIT; 2659 if (flags & PIPE_BARRIER_STREAMOUT_BUFFER) 2660 gl_barrier |= GL_TRANSFORM_FEEDBACK_BARRIER_BIT; 2661 if (flags & PIPE_BARRIER_SHADER_BUFFER) { 2662 gl_barrier |= GL_ATOMIC_COUNTER_BARRIER_BIT; 2663 if (has_feature(feat_ssbo_barrier)) 2664 gl_barrier |= GL_SHADER_STORAGE_BARRIER_BIT; 2665 } 2666 } 2667 glMemoryBarrier(gl_barrier); 2668 } 2669 2670 void vrend_texture_barrier(UNUSED struct vrend_context *ctx, 2671 unsigned flags) 2672 { 2673 if (!has_feature(feat_texture_barrier)) 2674 return; 2675 2676 if (flags == PIPE_TEXTURE_BARRIER_SAMPLER) 2677 glTextureBarrier(); 2678 } 2679 2680 static void vrend_destroy_shader_object(void *obj_ptr) 2681 { 2682 struct vrend_shader_selector *state = obj_ptr; 2683 2684 vrend_shader_state_reference(&state, NULL); 2685 } 2686 2687 static inline void vrend_fill_shader_key(struct vrend_context *ctx, 2688 unsigned type, 2689 struct vrend_shader_key *key) 2690 { 2691 if (vrend_state.use_core_profile == true) { 2692 int i; 2693 bool add_alpha_test = true; 2694 key->cbufs_are_a8_bitmask = 0; 2695 for (i = 0; i < ctx->sub->nr_cbufs; i++) { 2696 if (!ctx->sub->surf[i]) 2697 continue; 2698 if (vrend_format_is_emulated_alpha(ctx->sub->surf[i]->format)) 2699 key->cbufs_are_a8_bitmask |= (1 << i); 2700 if (util_format_is_pure_integer(ctx->sub->surf[i]->format)) 2701 add_alpha_test = false; 2702 } 2703 if (add_alpha_test) { 2704 key->add_alpha_test = ctx->sub->dsa_state.alpha.enabled; 2705 key->alpha_test = ctx->sub->dsa_state.alpha.func; 2706 key->alpha_ref_val = ctx->sub->dsa_state.alpha.ref_value; 2707 } 2708 2709 key->pstipple_tex = ctx->sub->rs_state.poly_stipple_enable; 2710 key->color_two_side = ctx->sub->rs_state.light_twoside; 2711 2712 key->clip_plane_enable = ctx->sub->rs_state.clip_plane_enable; 2713 key->flatshade = ctx->sub->rs_state.flatshade ? true : false; 2714 } else { 2715 key->add_alpha_test = 0; 2716 key->pstipple_tex = 0; 2717 } 2718 key->invert_fs_origin = !ctx->sub->inverted_fbo_content; 2719 key->coord_replace = ctx->sub->rs_state.point_quad_rasterization ? ctx->sub->rs_state.sprite_coord_enable : 0; 2720 2721 if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY]) 2722 key->gs_present = true; 2723 if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]) 2724 key->tcs_present = true; 2725 if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) 2726 key->tes_present = true; 2727 2728 int prev_type = -1; 2729 2730 switch (type) { 2731 case PIPE_SHADER_GEOMETRY: 2732 if (key->tcs_present || key->tes_present) 2733 prev_type = PIPE_SHADER_TESS_EVAL; 2734 else 2735 prev_type = PIPE_SHADER_VERTEX; 2736 break; 2737 case PIPE_SHADER_FRAGMENT: 2738 if (key->gs_present) 2739 prev_type = PIPE_SHADER_GEOMETRY; 2740 else if (key->tcs_present || key->tes_present) 2741 prev_type = PIPE_SHADER_TESS_EVAL; 2742 else 2743 prev_type = PIPE_SHADER_VERTEX; 2744 break; 2745 case PIPE_SHADER_TESS_EVAL: 2746 prev_type = PIPE_SHADER_TESS_CTRL; 2747 break; 2748 case PIPE_SHADER_TESS_CTRL: 2749 prev_type = PIPE_SHADER_VERTEX; 2750 break; 2751 default: 2752 break; 2753 } 2754 if (prev_type != -1 && ctx->sub->shaders[prev_type]) { 2755 key->prev_stage_pervertex_out = ctx->sub->shaders[prev_type]->sinfo.has_pervertex_out; 2756 key->prev_stage_num_clip_out = ctx->sub->shaders[prev_type]->sinfo.num_clip_out; 2757 key->prev_stage_num_cull_out = ctx->sub->shaders[prev_type]->sinfo.num_cull_out; 2758 key->num_indirect_generic_inputs = ctx->sub->shaders[prev_type]->sinfo.num_indirect_generic_outputs; 2759 key->num_indirect_patch_inputs = ctx->sub->shaders[prev_type]->sinfo.num_indirect_patch_outputs; 2760 } 2761 2762 int next_type = -1; 2763 switch (type) { 2764 case PIPE_SHADER_VERTEX: 2765 if (key->tcs_present) 2766 next_type = PIPE_SHADER_TESS_CTRL; 2767 else if (key->gs_present) 2768 next_type = PIPE_SHADER_GEOMETRY; 2769 else 2770 next_type = PIPE_SHADER_FRAGMENT; 2771 break; 2772 case PIPE_SHADER_TESS_CTRL: 2773 next_type = PIPE_SHADER_TESS_EVAL; 2774 break; 2775 case PIPE_SHADER_GEOMETRY: 2776 next_type = PIPE_SHADER_FRAGMENT; 2777 break; 2778 case PIPE_SHADER_TESS_EVAL: 2779 if (key->gs_present) 2780 next_type = PIPE_SHADER_GEOMETRY; 2781 else 2782 next_type = PIPE_SHADER_FRAGMENT; 2783 default: 2784 break; 2785 } 2786 2787 if (next_type != -1 && ctx->sub->shaders[next_type]) { 2788 key->num_indirect_generic_outputs = ctx->sub->shaders[next_type]->sinfo.num_indirect_generic_inputs; 2789 key->num_indirect_patch_outputs = ctx->sub->shaders[next_type]->sinfo.num_indirect_patch_inputs; 2790 } 2791 } 2792 2793 static inline int conv_shader_type(int type) 2794 { 2795 switch (type) { 2796 case PIPE_SHADER_VERTEX: return GL_VERTEX_SHADER; 2797 case PIPE_SHADER_FRAGMENT: return GL_FRAGMENT_SHADER; 2798 case PIPE_SHADER_GEOMETRY: return GL_GEOMETRY_SHADER; 2799 case PIPE_SHADER_TESS_CTRL: return GL_TESS_CONTROL_SHADER; 2800 case PIPE_SHADER_TESS_EVAL: return GL_TESS_EVALUATION_SHADER; 2801 case PIPE_SHADER_COMPUTE: return GL_COMPUTE_SHADER; 2802 default: 2803 return 0; 2804 }; 2805 } 2806 2807 static int vrend_shader_create(struct vrend_context *ctx, 2808 struct vrend_shader *shader, 2809 struct vrend_shader_key key) 2810 { 2811 2812 if (!shader->sel->tokens) { 2813 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SHADER, 0); 2814 return -1; 2815 } 2816 2817 shader->id = glCreateShader(conv_shader_type(shader->sel->type)); 2818 shader->compiled_fs_id = 0; 2819 shader->glsl_prog = vrend_convert_shader(&ctx->shader_cfg, shader->sel->tokens, shader->sel->req_local_mem, &key, &shader->sel->sinfo); 2820 if (!shader->glsl_prog) { 2821 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SHADER, 0); 2822 glDeleteShader(shader->id); 2823 return -1; 2824 } 2825 shader->key = key; 2826 if (1) {//shader->sel->type == PIPE_SHADER_FRAGMENT || shader->sel->type == PIPE_SHADER_GEOMETRY) { 2827 bool ret; 2828 2829 ret = vrend_compile_shader(ctx, shader); 2830 if (ret == false) { 2831 glDeleteShader(shader->id); 2832 free(shader->glsl_prog); 2833 return -1; 2834 } 2835 } 2836 return 0; 2837 } 2838 2839 static int vrend_shader_select(struct vrend_context *ctx, 2840 struct vrend_shader_selector *sel, 2841 bool *dirty) 2842 { 2843 struct vrend_shader_key key; 2844 struct vrend_shader *shader = NULL; 2845 int r; 2846 2847 memset(&key, 0, sizeof(key)); 2848 vrend_fill_shader_key(ctx, sel->type, &key); 2849 2850 if (sel->current && !memcmp(&sel->current->key, &key, sizeof(key))) 2851 return 0; 2852 2853 if (sel->num_shaders > 1) { 2854 struct vrend_shader *p = sel->current, *c = p->next_variant; 2855 while (c && memcmp(&c->key, &key, sizeof(key)) != 0) { 2856 p = c; 2857 c = c->next_variant; 2858 } 2859 if (c) { 2860 p->next_variant = c->next_variant; 2861 shader = c; 2862 } 2863 } 2864 2865 if (!shader) { 2866 shader = CALLOC_STRUCT(vrend_shader); 2867 shader->sel = sel; 2868 list_inithead(&shader->programs); 2869 2870 r = vrend_shader_create(ctx, shader, key); 2871 if (r) { 2872 sel->current = NULL; 2873 FREE(shader); 2874 return r; 2875 } 2876 sel->num_shaders++; 2877 } 2878 if (dirty) 2879 *dirty = true; 2880 2881 shader->next_variant = sel->current; 2882 sel->current = shader; 2883 return 0; 2884 } 2885 2886 static void *vrend_create_shader_state(UNUSED struct vrend_context *ctx, 2887 const struct pipe_stream_output_info *so_info, 2888 uint32_t req_local_mem, 2889 unsigned pipe_shader_type) 2890 { 2891 struct vrend_shader_selector *sel = CALLOC_STRUCT(vrend_shader_selector); 2892 2893 if (!sel) 2894 return NULL; 2895 2896 sel->req_local_mem = req_local_mem; 2897 sel->type = pipe_shader_type; 2898 sel->sinfo.so_info = *so_info; 2899 pipe_reference_init(&sel->reference, 1); 2900 2901 return sel; 2902 } 2903 2904 static int vrend_finish_shader(struct vrend_context *ctx, 2905 struct vrend_shader_selector *sel, 2906 const struct tgsi_token *tokens) 2907 { 2908 int r; 2909 2910 sel->tokens = tgsi_dup_tokens(tokens); 2911 2912 r = vrend_shader_select(ctx, sel, NULL); 2913 if (r) { 2914 return EINVAL; 2915 } 2916 return 0; 2917 } 2918 2919 int vrend_create_shader(struct vrend_context *ctx, 2920 uint32_t handle, 2921 const struct pipe_stream_output_info *so_info, 2922 uint32_t req_local_mem, 2923 const char *shd_text, uint32_t offlen, uint32_t num_tokens, 2924 uint32_t type, uint32_t pkt_length) 2925 { 2926 struct vrend_shader_selector *sel = NULL; 2927 int ret_handle; 2928 bool new_shader = true, long_shader = false; 2929 bool finished = false; 2930 int ret; 2931 2932 if (type > PIPE_SHADER_COMPUTE) 2933 return EINVAL; 2934 2935 if (!has_feature(feat_geometry_shader) && 2936 type == PIPE_SHADER_GEOMETRY) 2937 return EINVAL; 2938 2939 if (!has_feature(feat_tessellation) && 2940 (type == PIPE_SHADER_TESS_CTRL || 2941 type == PIPE_SHADER_TESS_EVAL)) 2942 return EINVAL; 2943 2944 if (!has_feature(feat_compute_shader) && 2945 type == PIPE_SHADER_COMPUTE) 2946 return EINVAL; 2947 2948 if (offlen & VIRGL_OBJ_SHADER_OFFSET_CONT) 2949 new_shader = false; 2950 else if (((offlen + 3) / 4) > pkt_length) 2951 long_shader = true; 2952 2953 /* if we have an in progress one - don't allow a new shader 2954 of that type or a different handle. */ 2955 if (ctx->sub->long_shader_in_progress_handle[type]) { 2956 if (new_shader == true) 2957 return EINVAL; 2958 if (handle != ctx->sub->long_shader_in_progress_handle[type]) 2959 return EINVAL; 2960 } 2961 2962 if (new_shader) { 2963 sel = vrend_create_shader_state(ctx, so_info, req_local_mem, type); 2964 if (sel == NULL) 2965 return ENOMEM; 2966 2967 if (long_shader) { 2968 sel->buf_len = ((offlen + 3) / 4) * 4; /* round up buffer size */ 2969 sel->tmp_buf = malloc(sel->buf_len); 2970 if (!sel->tmp_buf) { 2971 ret = ENOMEM; 2972 goto error; 2973 } 2974 memcpy(sel->tmp_buf, shd_text, pkt_length * 4); 2975 sel->buf_offset = pkt_length * 4; 2976 ctx->sub->long_shader_in_progress_handle[type] = handle; 2977 } else 2978 finished = true; 2979 } else { 2980 sel = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_SHADER); 2981 if (!sel) { 2982 fprintf(stderr, "got continuation without original shader %d\n", handle); 2983 ret = EINVAL; 2984 goto error; 2985 } 2986 2987 offlen &= ~VIRGL_OBJ_SHADER_OFFSET_CONT; 2988 if (offlen != sel->buf_offset) { 2989 fprintf(stderr, "Got mismatched shader continuation %d vs %d\n", 2990 offlen, sel->buf_offset); 2991 ret = EINVAL; 2992 goto error; 2993 } 2994 2995 /*make sure no overflow */ 2996 if (pkt_length * 4 < pkt_length || 2997 pkt_length * 4 + sel->buf_offset < pkt_length * 4 || 2998 pkt_length * 4 + sel->buf_offset < sel->buf_offset) { 2999 ret = EINVAL; 3000 goto error; 3001 } 3002 3003 if ((pkt_length * 4 + sel->buf_offset) > sel->buf_len) { 3004 fprintf(stderr, "Got too large shader continuation %d vs %d\n", 3005 pkt_length * 4 + sel->buf_offset, sel->buf_len); 3006 ret = EINVAL; 3007 goto error; 3008 } 3009 3010 memcpy(sel->tmp_buf + sel->buf_offset, shd_text, pkt_length * 4); 3011 3012 sel->buf_offset += pkt_length * 4; 3013 if (sel->buf_offset >= sel->buf_len) { 3014 finished = true; 3015 shd_text = sel->tmp_buf; 3016 } 3017 } 3018 3019 if (finished) { 3020 struct tgsi_token *tokens; 3021 3022 tokens = calloc(num_tokens + 10, sizeof(struct tgsi_token)); 3023 if (!tokens) { 3024 ret = ENOMEM; 3025 goto error; 3026 } 3027 3028 if (vrend_dump_shaders) 3029 fprintf(stderr,"shader\n%s\n", shd_text); 3030 if (!tgsi_text_translate((const char *)shd_text, tokens, num_tokens + 10)) { 3031 free(tokens); 3032 ret = EINVAL; 3033 goto error; 3034 } 3035 3036 if (vrend_finish_shader(ctx, sel, tokens)) { 3037 free(tokens); 3038 ret = EINVAL; 3039 goto error; 3040 } else { 3041 free(sel->tmp_buf); 3042 sel->tmp_buf = NULL; 3043 } 3044 free(tokens); 3045 ctx->sub->long_shader_in_progress_handle[type] = 0; 3046 } 3047 3048 if (new_shader) { 3049 ret_handle = vrend_renderer_object_insert(ctx, sel, sizeof(*sel), handle, VIRGL_OBJECT_SHADER); 3050 if (ret_handle == 0) { 3051 ret = ENOMEM; 3052 goto error; 3053 } 3054 } 3055 3056 return 0; 3057 3058 error: 3059 if (new_shader) 3060 vrend_destroy_shader_selector(sel); 3061 else 3062 vrend_renderer_object_destroy(ctx, handle); 3063 3064 return ret; 3065 } 3066 3067 void vrend_bind_shader(struct vrend_context *ctx, 3068 uint32_t handle, uint32_t type) 3069 { 3070 struct vrend_shader_selector *sel; 3071 3072 if (type > PIPE_SHADER_COMPUTE) 3073 return; 3074 3075 if (handle == 0) { 3076 if (type == PIPE_SHADER_COMPUTE) 3077 ctx->sub->cs_shader_dirty = true; 3078 else 3079 ctx->sub->shader_dirty = true; 3080 vrend_shader_state_reference(&ctx->sub->shaders[type], NULL); 3081 return; 3082 } 3083 3084 sel = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_SHADER); 3085 if (!sel) 3086 return; 3087 3088 if (sel->type != type) 3089 return; 3090 3091 if (ctx->sub->shaders[sel->type] != sel) { 3092 if (type == PIPE_SHADER_COMPUTE) 3093 ctx->sub->cs_shader_dirty = true; 3094 else 3095 ctx->sub->shader_dirty = true; 3096 ctx->sub->prog_ids[sel->type] = 0; 3097 } 3098 3099 vrend_shader_state_reference(&ctx->sub->shaders[sel->type], sel); 3100 } 3101 3102 void vrend_clear(struct vrend_context *ctx, 3103 unsigned buffers, 3104 const union pipe_color_union *color, 3105 double depth, unsigned stencil) 3106 { 3107 GLbitfield bits = 0; 3108 3109 if (ctx->in_error) 3110 return; 3111 3112 if (ctx->ctx_switch_pending) 3113 vrend_finish_context_switch(ctx); 3114 3115 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->sub->fb_id); 3116 3117 vrend_update_frontface_state(ctx); 3118 if (ctx->sub->stencil_state_dirty) 3119 vrend_update_stencil_state(ctx); 3120 if (ctx->sub->scissor_state_dirty) 3121 vrend_update_scissor_state(ctx); 3122 if (ctx->sub->viewport_state_dirty) 3123 vrend_update_viewport_state(ctx); 3124 3125 vrend_use_program(ctx, 0); 3126 3127 if (buffers & PIPE_CLEAR_COLOR) { 3128 if (ctx->sub->nr_cbufs && ctx->sub->surf[0] && vrend_format_is_emulated_alpha(ctx->sub->surf[0]->format)) { 3129 glClearColor(color->f[3], 0.0, 0.0, 0.0); 3130 } else { 3131 glClearColor(color->f[0], color->f[1], color->f[2], color->f[3]); 3132 } 3133 3134 /* This function implements Gallium's full clear callback (st->pipe->clear) on the host. This 3135 callback requires no color component be masked. We must unmask all components before 3136 calling glClear* and restore the previous colormask afterwards, as Gallium expects. */ 3137 if (ctx->sub->hw_blend_state.independent_blend_enable && 3138 has_feature(feat_indep_blend)) { 3139 int i; 3140 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) 3141 glColorMaskIndexedEXT(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 3142 } else 3143 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 3144 } 3145 3146 if (buffers & PIPE_CLEAR_DEPTH) { 3147 /* gallium clears don't respect depth mask */ 3148 glDepthMask(GL_TRUE); 3149 if (vrend_state.use_gles) { 3150 if (0.0f < depth && depth > 1.0f) { 3151 // Only warn, it is clamped by the function. 3152 report_gles_warn(ctx, GLES_WARN_DEPTH_CLEAR, 0); 3153 } 3154 glClearDepthf(depth); 3155 } else { 3156 glClearDepth(depth); 3157 } 3158 } 3159 3160 if (buffers & PIPE_CLEAR_STENCIL) { 3161 glStencilMask(~0u); 3162 glClearStencil(stencil); 3163 } 3164 3165 if (ctx->sub->hw_rs_state.rasterizer_discard) 3166 glDisable(GL_RASTERIZER_DISCARD); 3167 3168 if (buffers & PIPE_CLEAR_COLOR) { 3169 uint32_t mask = 0; 3170 int i; 3171 for (i = 0; i < ctx->sub->nr_cbufs; i++) { 3172 if (ctx->sub->surf[i]) 3173 mask |= (1 << i); 3174 } 3175 if (mask != (buffers >> 2)) { 3176 mask = buffers >> 2; 3177 while (mask) { 3178 i = u_bit_scan(&mask); 3179 if (i < PIPE_MAX_COLOR_BUFS && ctx->sub->surf[i] && util_format_is_pure_uint(ctx->sub->surf[i] && ctx->sub->surf[i]->format)) 3180 glClearBufferuiv(GL_COLOR, 3181 i, (GLuint *)color); 3182 else if (i < PIPE_MAX_COLOR_BUFS && ctx->sub->surf[i] && util_format_is_pure_sint(ctx->sub->surf[i] && ctx->sub->surf[i]->format)) 3183 glClearBufferiv(GL_COLOR, 3184 i, (GLint *)color); 3185 else 3186 glClearBufferfv(GL_COLOR, 3187 i, (GLfloat *)color); 3188 } 3189 } 3190 else 3191 bits |= GL_COLOR_BUFFER_BIT; 3192 } 3193 if (buffers & PIPE_CLEAR_DEPTH) 3194 bits |= GL_DEPTH_BUFFER_BIT; 3195 if (buffers & PIPE_CLEAR_STENCIL) 3196 bits |= GL_STENCIL_BUFFER_BIT; 3197 3198 if (bits) 3199 glClear(bits); 3200 3201 /* Is it really necessary to restore the old states? The only reason we 3202 * get here is because the guest cleared all those states but gallium 3203 * didn't forward them before calling the clear command 3204 */ 3205 if (ctx->sub->hw_rs_state.rasterizer_discard) 3206 glEnable(GL_RASTERIZER_DISCARD); 3207 3208 if (buffers & PIPE_CLEAR_DEPTH) { 3209 if (!ctx->sub->dsa_state.depth.writemask) 3210 glDepthMask(GL_FALSE); 3211 } 3212 3213 /* Restore previous stencil buffer write masks for both front and back faces */ 3214 if (buffers & PIPE_CLEAR_STENCIL) { 3215 glStencilMaskSeparate(GL_FRONT, ctx->sub->dsa_state.stencil[0].writemask); 3216 glStencilMaskSeparate(GL_BACK, ctx->sub->dsa_state.stencil[1].writemask); 3217 } 3218 3219 /* Restore previous colormask */ 3220 if (buffers & PIPE_CLEAR_COLOR) { 3221 if (ctx->sub->hw_blend_state.independent_blend_enable && 3222 has_feature(feat_indep_blend)) { 3223 int i; 3224 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { 3225 struct pipe_blend_state *blend = &ctx->sub->hw_blend_state; 3226 glColorMaskIndexedEXT(i, blend->rt[i].colormask & PIPE_MASK_R ? GL_TRUE : GL_FALSE, 3227 blend->rt[i].colormask & PIPE_MASK_G ? GL_TRUE : GL_FALSE, 3228 blend->rt[i].colormask & PIPE_MASK_B ? GL_TRUE : GL_FALSE, 3229 blend->rt[i].colormask & PIPE_MASK_A ? GL_TRUE : GL_FALSE); 3230 } 3231 } else { 3232 glColorMask(ctx->sub->hw_blend_state.rt[0].colormask & PIPE_MASK_R ? GL_TRUE : GL_FALSE, 3233 ctx->sub->hw_blend_state.rt[0].colormask & PIPE_MASK_G ? GL_TRUE : GL_FALSE, 3234 ctx->sub->hw_blend_state.rt[0].colormask & PIPE_MASK_B ? GL_TRUE : GL_FALSE, 3235 ctx->sub->hw_blend_state.rt[0].colormask & PIPE_MASK_A ? GL_TRUE : GL_FALSE); 3236 } 3237 } 3238 } 3239 3240 static void vrend_update_scissor_state(struct vrend_context *ctx) 3241 { 3242 struct pipe_scissor_state *ss; 3243 struct pipe_rasterizer_state *state = &ctx->sub->rs_state; 3244 GLint y; 3245 GLuint idx; 3246 unsigned mask = ctx->sub->scissor_state_dirty; 3247 3248 if (state->scissor) 3249 glEnable(GL_SCISSOR_TEST); 3250 else 3251 glDisable(GL_SCISSOR_TEST); 3252 3253 while (mask) { 3254 idx = u_bit_scan(&mask); 3255 if (idx >= PIPE_MAX_VIEWPORTS) { 3256 vrend_report_buffer_error(ctx, 0); 3257 break; 3258 } 3259 ss = &ctx->sub->ss[idx]; 3260 if (ctx->sub->viewport_is_negative) 3261 y = ss->miny; 3262 else 3263 y = ss->miny; 3264 3265 if (idx > 0 && has_feature(feat_viewport_array)) 3266 glScissorIndexed(idx, ss->minx, y, ss->maxx - ss->minx, ss->maxy - ss->miny); 3267 else 3268 glScissor(ss->minx, y, ss->maxx - ss->minx, ss->maxy - ss->miny); 3269 } 3270 ctx->sub->scissor_state_dirty = 0; 3271 } 3272 3273 static void vrend_update_viewport_state(struct vrend_context *ctx) 3274 { 3275 GLint cy; 3276 unsigned mask = ctx->sub->viewport_state_dirty; 3277 int idx; 3278 while (mask) { 3279 idx = u_bit_scan(&mask); 3280 3281 if (ctx->sub->viewport_is_negative) 3282 cy = ctx->sub->vps[idx].cur_y - ctx->sub->vps[idx].height; 3283 else 3284 cy = ctx->sub->vps[idx].cur_y; 3285 if (idx > 0 && has_feature(feat_viewport_array)) 3286 glViewportIndexedf(idx, ctx->sub->vps[idx].cur_x, cy, ctx->sub->vps[idx].width, ctx->sub->vps[idx].height); 3287 else 3288 glViewport(ctx->sub->vps[idx].cur_x, cy, ctx->sub->vps[idx].width, ctx->sub->vps[idx].height); 3289 } 3290 3291 ctx->sub->viewport_state_dirty = 0; 3292 } 3293 3294 static GLenum get_gs_xfb_mode(GLenum mode) 3295 { 3296 switch (mode) { 3297 case GL_POINTS: 3298 return GL_POINTS; 3299 case GL_LINE_STRIP: 3300 return GL_LINES; 3301 case GL_TRIANGLE_STRIP: 3302 return GL_TRIANGLES; 3303 default: 3304 fprintf(stderr, "illegal gs transform feedback mode %d\n", mode); 3305 return GL_POINTS; 3306 } 3307 } 3308 3309 static GLenum get_tess_xfb_mode(int mode, bool is_point_mode) 3310 { 3311 if (is_point_mode) 3312 return GL_POINTS; 3313 switch (mode) { 3314 case GL_QUADS: 3315 case GL_TRIANGLES: 3316 return GL_TRIANGLES; 3317 case GL_LINES: 3318 return GL_LINES; 3319 default: 3320 fprintf(stderr, "illegal gs transform feedback mode %d\n", mode); 3321 return GL_POINTS; 3322 } 3323 } 3324 3325 static GLenum get_xfb_mode(GLenum mode) 3326 { 3327 switch (mode) { 3328 case GL_POINTS: 3329 return GL_POINTS; 3330 case GL_TRIANGLES: 3331 case GL_TRIANGLE_STRIP: 3332 case GL_TRIANGLE_FAN: 3333 case GL_QUADS: 3334 case GL_QUAD_STRIP: 3335 case GL_POLYGON: 3336 return GL_TRIANGLES; 3337 case GL_LINES: 3338 case GL_LINE_LOOP: 3339 case GL_LINE_STRIP: 3340 return GL_LINES; 3341 default: 3342 fprintf(stderr, "failed to translate TFB %d\n", mode); 3343 return GL_POINTS; 3344 } 3345 } 3346 3347 static void vrend_draw_bind_vertex_legacy(struct vrend_context *ctx, 3348 struct vrend_vertex_element_array *va) 3349 { 3350 uint32_t num_enable; 3351 uint32_t enable_bitmask; 3352 uint32_t disable_bitmask; 3353 int i; 3354 3355 num_enable = va->count; 3356 enable_bitmask = 0; 3357 disable_bitmask = ~((1ull << num_enable) - 1); 3358 for (i = 0; i < (int)va->count; i++) { 3359 struct vrend_vertex_element *ve = &va->elements[i]; 3360 int vbo_index = ve->base.vertex_buffer_index; 3361 struct vrend_resource *res; 3362 GLint loc; 3363 3364 if (i >= ctx->sub->prog->ss[PIPE_SHADER_VERTEX]->sel->sinfo.num_inputs) { 3365 /* XYZZY: debug this? */ 3366 num_enable = ctx->sub->prog->ss[PIPE_SHADER_VERTEX]->sel->sinfo.num_inputs; 3367 break; 3368 } 3369 res = (struct vrend_resource *)ctx->sub->vbo[vbo_index].buffer; 3370 3371 if (!res) { 3372 fprintf(stderr,"cannot find vbo buf %d %d %d\n", i, va->count, ctx->sub->prog->ss[PIPE_SHADER_VERTEX]->sel->sinfo.num_inputs); 3373 continue; 3374 } 3375 3376 if (vrend_state.use_explicit_locations || has_feature(feat_gles31_vertex_attrib_binding)) { 3377 loc = i; 3378 } else { 3379 if (ctx->sub->prog->attrib_locs) { 3380 loc = ctx->sub->prog->attrib_locs[i]; 3381 } else loc = -1; 3382 3383 if (loc == -1) { 3384 fprintf(stderr,"%s: cannot find loc %d %d %d\n", ctx->debug_name, i, va->count, ctx->sub->prog->ss[PIPE_SHADER_VERTEX]->sel->sinfo.num_inputs); 3385 num_enable--; 3386 if (i == 0) { 3387 fprintf(stderr,"%s: shader probably didn't compile - skipping rendering\n", ctx->debug_name); 3388 return; 3389 } 3390 continue; 3391 } 3392 } 3393 3394 if (ve->type == GL_FALSE) { 3395 fprintf(stderr,"failed to translate vertex type - skipping render\n"); 3396 return; 3397 } 3398 3399 glBindBuffer(GL_ARRAY_BUFFER, res->id); 3400 3401 if (ctx->sub->vbo[vbo_index].stride == 0) { 3402 void *data; 3403 /* for 0 stride we are kinda screwed */ 3404 data = glMapBufferRange(GL_ARRAY_BUFFER, ctx->sub->vbo[vbo_index].buffer_offset, ve->nr_chan * sizeof(GLfloat), GL_MAP_READ_BIT); 3405 3406 switch (ve->nr_chan) { 3407 case 1: 3408 glVertexAttrib1fv(loc, data); 3409 break; 3410 case 2: 3411 glVertexAttrib2fv(loc, data); 3412 break; 3413 case 3: 3414 glVertexAttrib3fv(loc, data); 3415 break; 3416 case 4: 3417 default: 3418 glVertexAttrib4fv(loc, data); 3419 break; 3420 } 3421 glUnmapBuffer(GL_ARRAY_BUFFER); 3422 disable_bitmask |= (1 << loc); 3423 } else { 3424 enable_bitmask |= (1 << loc); 3425 if (util_format_is_pure_integer(ve->base.src_format)) { 3426 glVertexAttribIPointer(loc, ve->nr_chan, ve->type, ctx->sub->vbo[vbo_index].stride, (void *)(unsigned long)(ve->base.src_offset + ctx->sub->vbo[vbo_index].buffer_offset)); 3427 } else { 3428 glVertexAttribPointer(loc, ve->nr_chan, ve->type, ve->norm, ctx->sub->vbo[vbo_index].stride, (void *)(unsigned long)(ve->base.src_offset + ctx->sub->vbo[vbo_index].buffer_offset)); 3429 } 3430 glVertexAttribDivisorARB(loc, ve->base.instance_divisor); 3431 } 3432 } 3433 if (ctx->sub->enabled_attribs_bitmask != enable_bitmask) { 3434 uint32_t mask = ctx->sub->enabled_attribs_bitmask & disable_bitmask; 3435 3436 while (mask) { 3437 i = u_bit_scan(&mask); 3438 glDisableVertexAttribArray(i); 3439 } 3440 ctx->sub->enabled_attribs_bitmask &= ~disable_bitmask; 3441 3442 mask = ctx->sub->enabled_attribs_bitmask ^ enable_bitmask; 3443 while (mask) { 3444 i = u_bit_scan(&mask); 3445 glEnableVertexAttribArray(i); 3446 } 3447 3448 ctx->sub->enabled_attribs_bitmask = enable_bitmask; 3449 } 3450 } 3451 3452 static void vrend_draw_bind_vertex_binding(struct vrend_context *ctx, 3453 struct vrend_vertex_element_array *va) 3454 { 3455 int i; 3456 3457 glBindVertexArray(va->id); 3458 3459 if (ctx->sub->vbo_dirty) { 3460 for (i = 0; i < ctx->sub->num_vbos; i++) { 3461 struct vrend_resource *res = (struct vrend_resource *)ctx->sub->vbo[i].buffer; 3462 if (!res) 3463 glBindVertexBuffer(i, 0, 0, 0); 3464 else 3465 glBindVertexBuffer(i, 3466 res->id, 3467 ctx->sub->vbo[i].buffer_offset, 3468 ctx->sub->vbo[i].stride); 3469 } 3470 for (i = ctx->sub->num_vbos; i < ctx->sub->old_num_vbos; i++) { 3471 glBindVertexBuffer(i, 0, 0, 0); 3472 } 3473 ctx->sub->vbo_dirty = false; 3474 } 3475 } 3476 3477 static void vrend_draw_bind_samplers_shader(struct vrend_context *ctx, 3478 int shader_type, 3479 int *sampler_id) 3480 { 3481 int index = 0; 3482 for (int i = 0; i < ctx->sub->views[shader_type].num_views; i++) { 3483 struct vrend_sampler_view *tview = ctx->sub->views[shader_type].views[i]; 3484 3485 if (!tview) 3486 continue; 3487 3488 if (!(ctx->sub->prog->samplers_used_mask[shader_type] & (1 << i))) 3489 continue; 3490 3491 if (ctx->sub->prog->samp_locs[shader_type]) 3492 glUniform1i(ctx->sub->prog->samp_locs[shader_type][index], *sampler_id); 3493 3494 if (ctx->sub->prog->shadow_samp_mask[shader_type] & (1 << i)) { 3495 glUniform4f(ctx->sub->prog->shadow_samp_mask_locs[shader_type][index], 3496 (tview->gl_swizzle_r == GL_ZERO || tview->gl_swizzle_r == GL_ONE) ? 0.0 : 1.0, 3497 (tview->gl_swizzle_g == GL_ZERO || tview->gl_swizzle_g == GL_ONE) ? 0.0 : 1.0, 3498 (tview->gl_swizzle_b == GL_ZERO || tview->gl_swizzle_b == GL_ONE) ? 0.0 : 1.0, 3499 (tview->gl_swizzle_a == GL_ZERO || tview->gl_swizzle_a == GL_ONE) ? 0.0 : 1.0); 3500 glUniform4f(ctx->sub->prog->shadow_samp_add_locs[shader_type][index], 3501 tview->gl_swizzle_r == GL_ONE ? 1.0 : 0.0, 3502 tview->gl_swizzle_g == GL_ONE ? 1.0 : 0.0, 3503 tview->gl_swizzle_b == GL_ONE ? 1.0 : 0.0, 3504 tview->gl_swizzle_a == GL_ONE ? 1.0 : 0.0); 3505 } 3506 3507 glActiveTexture(GL_TEXTURE0 + *sampler_id); 3508 if (tview->texture) { 3509 GLuint id; 3510 struct vrend_resource *texture = tview->texture; 3511 GLenum target = tview->target; 3512 3513 if (texture->is_buffer) { 3514 id = texture->tbo_tex_id; 3515 target = GL_TEXTURE_BUFFER; 3516 } else 3517 id = tview->id; 3518 3519 glBindTexture(target, id); 3520 if (ctx->sub->views[shader_type].old_ids[i] != id || ctx->sub->sampler_state_dirty) { 3521 vrend_apply_sampler_state(ctx, texture, shader_type, i, *sampler_id, tview->srgb_decode); 3522 ctx->sub->views[shader_type].old_ids[i] = id; 3523 } 3524 if (ctx->sub->rs_state.point_quad_rasterization) { 3525 if (vrend_state.use_core_profile == false) { 3526 if (ctx->sub->rs_state.sprite_coord_enable & (1 << i)) 3527 glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); 3528 else 3529 glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE); 3530 } 3531 } 3532 (*sampler_id)++; 3533 } 3534 index++; 3535 } 3536 } 3537 3538 static void vrend_draw_bind_ubo_shader(struct vrend_context *ctx, 3539 int shader_type, int *ubo_id) 3540 { 3541 uint32_t mask; 3542 int shader_ubo_idx; 3543 struct pipe_constant_buffer *cb; 3544 struct vrend_resource *res; 3545 struct vrend_shader_info* sinfo; 3546 3547 if (!has_feature(feat_ubo)) 3548 return; 3549 3550 if (!ctx->sub->const_bufs_used_mask[shader_type]) 3551 return; 3552 3553 if (!ctx->sub->prog->ubo_locs[shader_type]) 3554 return; 3555 3556 sinfo = &ctx->sub->prog->ss[shader_type]->sel->sinfo; 3557 3558 mask = ctx->sub->const_bufs_used_mask[shader_type]; 3559 while (mask) { 3560 /* The const_bufs_used_mask stores the gallium uniform buffer indices */ 3561 int i = u_bit_scan(&mask); 3562 3563 /* The cbs array is indexed using the gallium uniform buffer index */ 3564 cb = &ctx->sub->cbs[shader_type][i]; 3565 res = (struct vrend_resource *)cb->buffer; 3566 3567 /* Find the index of the uniform buffer in the array of shader ubo data */ 3568 for (shader_ubo_idx = 0; shader_ubo_idx < sinfo->num_ubos; shader_ubo_idx++) { 3569 if (sinfo->ubo_idx[shader_ubo_idx] == i) 3570 break; 3571 } 3572 if (shader_ubo_idx == sinfo->num_ubos) 3573 continue; 3574 3575 glBindBufferRange(GL_UNIFORM_BUFFER, *ubo_id, res->id, 3576 cb->buffer_offset, cb->buffer_size); 3577 /* The ubo_locs array is indexed using the shader ubo index */ 3578 glUniformBlockBinding(ctx->sub->prog->id, ctx->sub->prog->ubo_locs[shader_type][shader_ubo_idx], *ubo_id); 3579 (*ubo_id)++; 3580 } 3581 } 3582 3583 static void vrend_draw_bind_const_shader(struct vrend_context *ctx, 3584 int shader_type, bool new_program) 3585 { 3586 if (ctx->sub->consts[shader_type].consts && 3587 ctx->sub->prog->const_locs[shader_type] && 3588 (ctx->sub->const_dirty[shader_type] || new_program)) { 3589 for (int i = 0; i < ctx->sub->shaders[shader_type]->sinfo.num_consts; i++) { 3590 if (ctx->sub->prog->const_locs[shader_type][i] != -1) 3591 glUniform4uiv(ctx->sub->prog->const_locs[shader_type][i], 1, &ctx->sub->consts[shader_type].consts[i * 4]); 3592 } 3593 ctx->sub->const_dirty[shader_type] = false; 3594 } 3595 } 3596 3597 static void vrend_draw_bind_ssbo_shader(struct vrend_context *ctx, int shader_type) 3598 { 3599 uint32_t mask; 3600 struct vrend_ssbo *ssbo; 3601 struct vrend_resource *res; 3602 int i; 3603 3604 if (!has_feature(feat_ssbo)) 3605 return; 3606 3607 if (!ctx->sub->prog->ssbo_locs[shader_type]) 3608 return; 3609 3610 if (!ctx->sub->ssbo_used_mask[shader_type]) 3611 return; 3612 3613 mask = ctx->sub->ssbo_used_mask[shader_type]; 3614 while (mask) { 3615 i = u_bit_scan(&mask); 3616 3617 ssbo = &ctx->sub->ssbo[shader_type][i]; 3618 res = (struct vrend_resource *)ssbo->res; 3619 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, res->id, 3620 ssbo->buffer_offset, ssbo->buffer_size); 3621 if (ctx->sub->prog->ssbo_locs[shader_type][i] != GL_INVALID_INDEX) { 3622 if (!vrend_state.use_gles) 3623 glShaderStorageBlockBinding(ctx->sub->prog->id, ctx->sub->prog->ssbo_locs[shader_type][i], i); 3624 else 3625 debug_printf("glShaderStorageBlockBinding not supported on gles \n"); 3626 } 3627 } 3628 } 3629 3630 static void vrend_draw_bind_images_shader(struct vrend_context *ctx, int shader_type) 3631 { 3632 GLenum access; 3633 GLboolean layered; 3634 struct vrend_image_view *iview; 3635 uint32_t mask, tex_id, level, first_layer; 3636 3637 if (!has_feature(feat_images)) 3638 return; 3639 3640 if (!ctx->sub->images_used_mask[shader_type]) 3641 return; 3642 3643 if (!ctx->sub->prog->img_locs[shader_type]) 3644 return; 3645 3646 mask = ctx->sub->images_used_mask[shader_type]; 3647 while (mask) { 3648 unsigned i = u_bit_scan(&mask); 3649 3650 if (!(ctx->sub->prog->images_used_mask[shader_type] & (1 << i))) 3651 continue; 3652 iview = &ctx->sub->image_views[shader_type][i]; 3653 tex_id = iview->texture->id; 3654 if (iview->texture->is_buffer) { 3655 if (!iview->texture->tbo_tex_id) 3656 glGenTextures(1, &iview->texture->tbo_tex_id); 3657 3658 /* glTexBuffer doesn't accept GL_RGBA8_SNORM, find an appropriate replacement. */ 3659 uint32_t format = (iview->format == GL_RGBA8_SNORM) ? GL_RGBA8UI : iview->format; 3660 3661 glBindBufferARB(GL_TEXTURE_BUFFER, iview->texture->id); 3662 glBindTexture(GL_TEXTURE_BUFFER, iview->texture->tbo_tex_id); 3663 glTexBuffer(GL_TEXTURE_BUFFER, format, iview->texture->id); 3664 tex_id = iview->texture->tbo_tex_id; 3665 level = first_layer = 0; 3666 layered = GL_TRUE; 3667 } else { 3668 level = iview->u.tex.level; 3669 first_layer = iview->u.tex.first_layer; 3670 layered = !((iview->texture->base.array_size > 1 || 3671 iview->texture->base.depth0 > 1) && (iview->u.tex.first_layer == iview->u.tex.last_layer)); 3672 } 3673 3674 if (!vrend_state.use_gles) 3675 glUniform1i(ctx->sub->prog->img_locs[shader_type][i], i); 3676 3677 switch (iview->access) { 3678 case PIPE_IMAGE_ACCESS_READ: 3679 access = GL_READ_ONLY; 3680 break; 3681 case PIPE_IMAGE_ACCESS_WRITE: 3682 access = GL_WRITE_ONLY; 3683 break; 3684 case PIPE_IMAGE_ACCESS_READ_WRITE: 3685 access = GL_READ_WRITE; 3686 break; 3687 default: 3688 fprintf(stderr, "Invalid access specified\n"); 3689 return; 3690 } 3691 3692 glBindImageTexture(i, tex_id, level, layered, first_layer, access, iview->format); 3693 } 3694 } 3695 3696 static void vrend_draw_bind_objects(struct vrend_context *ctx, bool new_program) 3697 { 3698 int ubo_id = 0, sampler_id = 0; 3699 for (int shader_type = PIPE_SHADER_VERTEX; shader_type <= ctx->sub->last_shader_idx; shader_type++) { 3700 vrend_draw_bind_ubo_shader(ctx, shader_type, &ubo_id); 3701 vrend_draw_bind_const_shader(ctx, shader_type, new_program); 3702 vrend_draw_bind_samplers_shader(ctx, shader_type, &sampler_id); 3703 vrend_draw_bind_images_shader(ctx, shader_type); 3704 vrend_draw_bind_ssbo_shader(ctx, shader_type); 3705 } 3706 3707 if (vrend_state.use_core_profile && ctx->sub->prog->fs_stipple_loc != -1) { 3708 glActiveTexture(GL_TEXTURE0 + sampler_id); 3709 glBindTexture(GL_TEXTURE_2D, ctx->pstipple_tex_id); 3710 glUniform1i(ctx->sub->prog->fs_stipple_loc, sampler_id); 3711 } 3712 ctx->sub->sampler_state_dirty = false; 3713 } 3714 3715 int vrend_draw_vbo(struct vrend_context *ctx, 3716 const struct pipe_draw_info *info, 3717 uint32_t cso, uint32_t indirect_handle, 3718 uint32_t indirect_draw_count_handle) 3719 { 3720 int i; 3721 bool new_program = false; 3722 struct vrend_resource *indirect_res = NULL; 3723 3724 if (ctx->in_error) 3725 return 0; 3726 3727 if (info->instance_count && !has_feature(feat_draw_instance)) 3728 return EINVAL; 3729 3730 if (info->start_instance && !has_feature(feat_base_instance)) 3731 return EINVAL; 3732 3733 if (indirect_handle) { 3734 if (!has_feature(feat_indirect_draw)) 3735 return EINVAL; 3736 indirect_res = vrend_renderer_ctx_res_lookup(ctx, indirect_handle); 3737 if (!indirect_res) { 3738 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, indirect_handle); 3739 return 0; 3740 } 3741 } 3742 3743 /* this must be zero until we support the feature */ 3744 if (indirect_draw_count_handle) { 3745 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, indirect_handle); 3746 return 0; 3747 } 3748 3749 if (ctx->ctx_switch_pending) 3750 vrend_finish_context_switch(ctx); 3751 3752 vrend_update_frontface_state(ctx); 3753 if (ctx->sub->stencil_state_dirty) 3754 vrend_update_stencil_state(ctx); 3755 if (ctx->sub->scissor_state_dirty) 3756 vrend_update_scissor_state(ctx); 3757 3758 if (ctx->sub->viewport_state_dirty) 3759 vrend_update_viewport_state(ctx); 3760 3761 vrend_patch_blend_state(ctx); 3762 3763 if (ctx->sub->shader_dirty) { 3764 struct vrend_linked_shader_program *prog; 3765 bool fs_dirty, vs_dirty, gs_dirty, tcs_dirty, tes_dirty; 3766 bool dual_src = util_blend_state_is_dual(&ctx->sub->blend_state, 0); 3767 bool same_prog; 3768 if (!ctx->sub->shaders[PIPE_SHADER_VERTEX] || !ctx->sub->shaders[PIPE_SHADER_FRAGMENT]) { 3769 fprintf(stderr,"dropping rendering due to missing shaders: %s\n", ctx->debug_name); 3770 return 0; 3771 } 3772 3773 vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_FRAGMENT], &fs_dirty); 3774 vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_VERTEX], &vs_dirty); 3775 if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY]) 3776 vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_GEOMETRY], &gs_dirty); 3777 if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]) 3778 vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_TESS_CTRL], &tcs_dirty); 3779 if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) 3780 vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_TESS_EVAL], &tes_dirty); 3781 3782 if (!ctx->sub->shaders[PIPE_SHADER_VERTEX]->current || 3783 !ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current || 3784 (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && !ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current) || 3785 (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && !ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current) || 3786 (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] && !ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current)) { 3787 fprintf(stderr, "failure to compile shader variants: %s\n", ctx->debug_name); 3788 return 0; 3789 } 3790 same_prog = true; 3791 if (ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_VERTEX]) 3792 same_prog = false; 3793 if (ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT]) 3794 same_prog = false; 3795 if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_GEOMETRY]) 3796 same_prog = false; 3797 if (ctx->sub->prog && ctx->sub->prog->dual_src_linked != dual_src) 3798 same_prog = false; 3799 if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_TESS_CTRL]) 3800 same_prog = false; 3801 if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] && ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL]) 3802 same_prog = false; 3803 3804 if (!same_prog) { 3805 prog = lookup_shader_program(ctx, 3806 ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id, 3807 ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id, 3808 ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id : 0, 3809 ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] ? ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id : 0, 3810 ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id : 0, 3811 dual_src); 3812 if (!prog) { 3813 prog = add_shader_program(ctx, 3814 ctx->sub->shaders[PIPE_SHADER_VERTEX]->current, 3815 ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current, 3816 ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current : NULL, 3817 ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] ? ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current : NULL, 3818 ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current : NULL); 3819 if (!prog) 3820 return 0; 3821 } 3822 3823 ctx->sub->last_shader_idx = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? PIPE_SHADER_TESS_EVAL : (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? PIPE_SHADER_GEOMETRY : PIPE_SHADER_FRAGMENT); 3824 } else 3825 prog = ctx->sub->prog; 3826 if (ctx->sub->prog != prog) { 3827 new_program = true; 3828 ctx->sub->prog_ids[PIPE_SHADER_VERTEX] = ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id; 3829 ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT] = ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id; 3830 if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY]) 3831 ctx->sub->prog_ids[PIPE_SHADER_GEOMETRY] = ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id; 3832 if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]) 3833 ctx->sub->prog_ids[PIPE_SHADER_TESS_CTRL] = ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id; 3834 if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) 3835 ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL] = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id; 3836 ctx->sub->prog = prog; 3837 } 3838 } 3839 if (!ctx->sub->prog) { 3840 fprintf(stderr,"dropping rendering due to missing shaders: %s\n", ctx->debug_name); 3841 return 0; 3842 } 3843 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->sub->fb_id); 3844 3845 vrend_use_program(ctx, ctx->sub->prog->id); 3846 3847 vrend_draw_bind_objects(ctx, new_program); 3848 3849 if (!ctx->sub->ve) { 3850 fprintf(stderr,"illegal VE setup - skipping renderering\n"); 3851 return 0; 3852 } 3853 glUniform1f(ctx->sub->prog->vs_ws_adjust_loc, ctx->sub->viewport_is_negative ? -1.0 : 1.0); 3854 3855 if (ctx->sub->rs_state.clip_plane_enable) { 3856 for (i = 0 ; i < 8; i++) { 3857 glUniform4fv(ctx->sub->prog->clip_locs[i], 1, (const GLfloat *)&ctx->sub->ucp_state.ucp[i]); 3858 } 3859 } 3860 3861 if (has_feature(feat_gles31_vertex_attrib_binding)) 3862 vrend_draw_bind_vertex_binding(ctx, ctx->sub->ve); 3863 else 3864 vrend_draw_bind_vertex_legacy(ctx, ctx->sub->ve); 3865 3866 for (i = 0 ; i < ctx->sub->prog->ss[PIPE_SHADER_VERTEX]->sel->sinfo.num_inputs; i++) { 3867 struct vrend_vertex_element_array *va = ctx->sub->ve; 3868 struct vrend_vertex_element *ve = &va->elements[i]; 3869 int vbo_index = ve->base.vertex_buffer_index; 3870 if (!ctx->sub->vbo[vbo_index].buffer) { 3871 fprintf(stderr, "VBO missing vertex buffer\n"); 3872 return 0; 3873 } 3874 } 3875 3876 if (info->indexed) { 3877 struct vrend_resource *res = (struct vrend_resource *)ctx->sub->ib.buffer; 3878 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, res->id); 3879 } else 3880 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 3881 3882 if (ctx->sub->current_so) { 3883 if (ctx->sub->current_so->xfb_state == XFB_STATE_STARTED_NEED_BEGIN) { 3884 if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY]) 3885 glBeginTransformFeedback(get_gs_xfb_mode(ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->sinfo.gs_out_prim)); 3886 else if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) 3887 glBeginTransformFeedback(get_tess_xfb_mode(ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->sinfo.tes_prim, 3888 ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->sinfo.tes_point_mode)); 3889 else 3890 glBeginTransformFeedback(get_xfb_mode(info->mode)); 3891 ctx->sub->current_so->xfb_state = XFB_STATE_STARTED; 3892 } else if (ctx->sub->current_so->xfb_state == XFB_STATE_PAUSED) { 3893 glResumeTransformFeedback(); 3894 ctx->sub->current_so->xfb_state = XFB_STATE_STARTED; 3895 } 3896 } 3897 3898 if (info->primitive_restart) { 3899 if (vrend_state.use_gles) { 3900 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); 3901 } else if (has_feature(feat_nv_prim_restart)) { 3902 glEnableClientState(GL_PRIMITIVE_RESTART_NV); 3903 glPrimitiveRestartIndexNV(info->restart_index); 3904 } else if (has_feature(feat_gl_prim_restart)) { 3905 glEnable(GL_PRIMITIVE_RESTART); 3906 glPrimitiveRestartIndex(info->restart_index); 3907 } 3908 } 3909 3910 if (has_feature(feat_indirect_draw)) { 3911 if (indirect_res) 3912 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect_res->id); 3913 else 3914 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); 3915 } 3916 3917 if (info->vertices_per_patch && has_feature(feat_tessellation)) 3918 glPatchParameteri(GL_PATCH_VERTICES, info->vertices_per_patch); 3919 3920 /* set the vertex state up now on a delay */ 3921 if (!info->indexed) { 3922 GLenum mode = info->mode; 3923 int count = cso ? cso : info->count; 3924 int start = cso ? 0 : info->start; 3925 3926 if (indirect_handle) 3927 glDrawArraysIndirect(mode, (GLvoid const *)(unsigned long)info->indirect.offset); 3928 else if (info->instance_count <= 1) 3929 glDrawArrays(mode, start, count); 3930 else if (info->start_instance) 3931 glDrawArraysInstancedBaseInstance(mode, start, count, info->instance_count, info->start_instance); 3932 else 3933 glDrawArraysInstancedARB(mode, start, count, info->instance_count); 3934 } else { 3935 GLenum elsz; 3936 GLenum mode = info->mode; 3937 switch (ctx->sub->ib.index_size) { 3938 case 1: 3939 elsz = GL_UNSIGNED_BYTE; 3940 break; 3941 case 2: 3942 elsz = GL_UNSIGNED_SHORT; 3943 break; 3944 case 4: 3945 default: 3946 elsz = GL_UNSIGNED_INT; 3947 break; 3948 } 3949 3950 if (indirect_handle) 3951 glDrawElementsIndirect(mode, elsz, (GLvoid const *)(unsigned long)info->indirect.offset); 3952 else if (info->index_bias) { 3953 if (info->instance_count > 1) 3954 glDrawElementsInstancedBaseVertex(mode, info->count, elsz, (void *)(unsigned long)ctx->sub->ib.offset, info->instance_count, info->index_bias); 3955 else if (info->min_index != 0 || info->max_index != (unsigned)-1) 3956 glDrawRangeElementsBaseVertex(mode, info->min_index, info->max_index, info->count, elsz, (void *)(unsigned long)ctx->sub->ib.offset, info->index_bias); 3957 else 3958 glDrawElementsBaseVertex(mode, info->count, elsz, (void *)(unsigned long)ctx->sub->ib.offset, info->index_bias); 3959 } else if (info->instance_count > 1) { 3960 glDrawElementsInstancedARB(mode, info->count, elsz, (void *)(unsigned long)ctx->sub->ib.offset, info->instance_count); 3961 } else if (info->min_index != 0 || info->max_index != (unsigned)-1) 3962 glDrawRangeElements(mode, info->min_index, info->max_index, info->count, elsz, (void *)(unsigned long)ctx->sub->ib.offset); 3963 else 3964 glDrawElements(mode, info->count, elsz, (void *)(unsigned long)ctx->sub->ib.offset); 3965 } 3966 3967 if (info->primitive_restart) { 3968 if (vrend_state.use_gles) { 3969 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); 3970 } else if (has_feature(feat_nv_prim_restart)) { 3971 glDisableClientState(GL_PRIMITIVE_RESTART_NV); 3972 } else if (has_feature(feat_gl_prim_restart)) { 3973 glDisable(GL_PRIMITIVE_RESTART); 3974 } 3975 } 3976 3977 if (ctx->sub->current_so && has_feature(feat_transform_feedback2)) { 3978 if (ctx->sub->current_so->xfb_state == XFB_STATE_STARTED) { 3979 glPauseTransformFeedback(); 3980 ctx->sub->current_so->xfb_state = XFB_STATE_PAUSED; 3981 } 3982 } 3983 return 0; 3984 } 3985 3986 void vrend_launch_grid(struct vrend_context *ctx, 3987 UNUSED uint32_t *block, 3988 uint32_t *grid, 3989 uint32_t indirect_handle, 3990 uint32_t indirect_offset) 3991 { 3992 bool new_program = false; 3993 struct vrend_resource *indirect_res = NULL; 3994 3995 if (!has_feature(feat_compute_shader)) 3996 return; 3997 3998 if (ctx->sub->cs_shader_dirty) { 3999 struct vrend_linked_shader_program *prog; 4000 bool same_prog, cs_dirty; 4001 if (!ctx->sub->shaders[PIPE_SHADER_COMPUTE]) { 4002 fprintf(stderr,"dropping rendering due to missing shaders: %s\n", ctx->debug_name); 4003 return; 4004 } 4005 4006 vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_COMPUTE], &cs_dirty); 4007 if (!ctx->sub->shaders[PIPE_SHADER_COMPUTE]->current) { 4008 fprintf(stderr, "failure to compile shader variants: %s\n", ctx->debug_name); 4009 return; 4010 } 4011 same_prog = true; 4012 if (ctx->sub->shaders[PIPE_SHADER_COMPUTE]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_COMPUTE]) 4013 same_prog = false; 4014 if (!same_prog) { 4015 prog = lookup_cs_shader_program(ctx, ctx->sub->shaders[PIPE_SHADER_COMPUTE]->current->id); 4016 if (!prog) { 4017 prog = add_cs_shader_program(ctx, ctx->sub->shaders[PIPE_SHADER_COMPUTE]->current); 4018 if (!prog) 4019 return; 4020 } 4021 } else 4022 prog = ctx->sub->prog; 4023 4024 if (ctx->sub->prog != prog) { 4025 new_program = true; 4026 ctx->sub->prog_ids[PIPE_SHADER_VERTEX] = -1; 4027 ctx->sub->prog_ids[PIPE_SHADER_COMPUTE] = ctx->sub->shaders[PIPE_SHADER_COMPUTE]->current->id; 4028 ctx->sub->prog = prog; 4029 } 4030 ctx->sub->shader_dirty = true; 4031 } 4032 vrend_use_program(ctx, ctx->sub->prog->id); 4033 4034 int sampler_id = 0, ubo_id = 0; 4035 vrend_draw_bind_ubo_shader(ctx, PIPE_SHADER_COMPUTE, &ubo_id); 4036 vrend_draw_bind_const_shader(ctx, PIPE_SHADER_COMPUTE, new_program); 4037 vrend_draw_bind_samplers_shader(ctx, PIPE_SHADER_COMPUTE, &sampler_id); 4038 vrend_draw_bind_images_shader(ctx, PIPE_SHADER_COMPUTE); 4039 vrend_draw_bind_ssbo_shader(ctx, PIPE_SHADER_COMPUTE); 4040 4041 if (indirect_handle) { 4042 indirect_res = vrend_renderer_ctx_res_lookup(ctx, indirect_handle); 4043 if (!indirect_res) { 4044 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, indirect_handle); 4045 return; 4046 } 4047 } 4048 4049 if (indirect_res) 4050 glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, indirect_res->id); 4051 else 4052 glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0); 4053 4054 if (indirect_res) { 4055 glDispatchComputeIndirect(indirect_offset); 4056 } else { 4057 glDispatchCompute(grid[0], grid[1], grid[2]); 4058 } 4059 } 4060 4061 static GLenum translate_blend_func(uint32_t pipe_blend) 4062 { 4063 switch(pipe_blend){ 4064 case PIPE_BLEND_ADD: return GL_FUNC_ADD; 4065 case PIPE_BLEND_SUBTRACT: return GL_FUNC_SUBTRACT; 4066 case PIPE_BLEND_REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT; 4067 case PIPE_BLEND_MIN: return GL_MIN; 4068 case PIPE_BLEND_MAX: return GL_MAX; 4069 default: 4070 assert("invalid blend token()" == NULL); 4071 return 0; 4072 } 4073 } 4074 4075 static GLenum translate_blend_factor(uint32_t pipe_factor) 4076 { 4077 switch (pipe_factor) { 4078 case PIPE_BLENDFACTOR_ONE: return GL_ONE; 4079 case PIPE_BLENDFACTOR_SRC_COLOR: return GL_SRC_COLOR; 4080 case PIPE_BLENDFACTOR_SRC_ALPHA: return GL_SRC_ALPHA; 4081 4082 case PIPE_BLENDFACTOR_DST_COLOR: return GL_DST_COLOR; 4083 case PIPE_BLENDFACTOR_DST_ALPHA: return GL_DST_ALPHA; 4084 4085 case PIPE_BLENDFACTOR_CONST_COLOR: return GL_CONSTANT_COLOR; 4086 case PIPE_BLENDFACTOR_CONST_ALPHA: return GL_CONSTANT_ALPHA; 4087 4088 case PIPE_BLENDFACTOR_SRC1_COLOR: return GL_SRC1_COLOR; 4089 case PIPE_BLENDFACTOR_SRC1_ALPHA: return GL_SRC1_ALPHA; 4090 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return GL_SRC_ALPHA_SATURATE; 4091 case PIPE_BLENDFACTOR_ZERO: return GL_ZERO; 4092 4093 4094 case PIPE_BLENDFACTOR_INV_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR; 4095 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA; 4096 4097 case PIPE_BLENDFACTOR_INV_DST_COLOR: return GL_ONE_MINUS_DST_COLOR; 4098 case PIPE_BLENDFACTOR_INV_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA; 4099 4100 case PIPE_BLENDFACTOR_INV_CONST_COLOR: return GL_ONE_MINUS_CONSTANT_COLOR; 4101 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return GL_ONE_MINUS_CONSTANT_ALPHA; 4102 4103 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return GL_ONE_MINUS_SRC1_COLOR; 4104 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return GL_ONE_MINUS_SRC1_ALPHA; 4105 4106 default: 4107 assert("invalid blend token()" == NULL); 4108 return 0; 4109 } 4110 } 4111 4112 static GLenum 4113 translate_logicop(GLuint pipe_logicop) 4114 { 4115 switch (pipe_logicop) { 4116 #define CASE(x) case PIPE_LOGICOP_##x: return GL_##x 4117 CASE(CLEAR); 4118 CASE(NOR); 4119 CASE(AND_INVERTED); 4120 CASE(COPY_INVERTED); 4121 CASE(AND_REVERSE); 4122 CASE(INVERT); 4123 CASE(XOR); 4124 CASE(NAND); 4125 CASE(AND); 4126 CASE(EQUIV); 4127 CASE(NOOP); 4128 CASE(OR_INVERTED); 4129 CASE(COPY); 4130 CASE(OR_REVERSE); 4131 CASE(OR); 4132 CASE(SET); 4133 default: 4134 assert("invalid logicop token()" == NULL); 4135 return 0; 4136 } 4137 #undef CASE 4138 } 4139 4140 static GLenum 4141 translate_stencil_op(GLuint op) 4142 { 4143 switch (op) { 4144 #define CASE(x) case PIPE_STENCIL_OP_##x: return GL_##x 4145 CASE(KEEP); 4146 CASE(ZERO); 4147 CASE(REPLACE); 4148 CASE(INCR); 4149 CASE(DECR); 4150 CASE(INCR_WRAP); 4151 CASE(DECR_WRAP); 4152 CASE(INVERT); 4153 default: 4154 assert("invalid stencilop token()" == NULL); 4155 return 0; 4156 } 4157 #undef CASE 4158 } 4159 4160 static inline bool is_dst_blend(int blend_factor) 4161 { 4162 return (blend_factor == PIPE_BLENDFACTOR_DST_ALPHA || 4163 blend_factor == PIPE_BLENDFACTOR_INV_DST_ALPHA); 4164 } 4165 4166 static inline int conv_a8_blend(int blend_factor) 4167 { 4168 if (blend_factor == PIPE_BLENDFACTOR_DST_ALPHA) 4169 return PIPE_BLENDFACTOR_DST_COLOR; 4170 if (blend_factor == PIPE_BLENDFACTOR_INV_DST_ALPHA) 4171 return PIPE_BLENDFACTOR_INV_DST_COLOR; 4172 return blend_factor; 4173 } 4174 4175 static inline int conv_dst_blend(int blend_factor) 4176 { 4177 if (blend_factor == PIPE_BLENDFACTOR_DST_ALPHA) 4178 return PIPE_BLENDFACTOR_ONE; 4179 if (blend_factor == PIPE_BLENDFACTOR_INV_DST_ALPHA) 4180 return PIPE_BLENDFACTOR_ZERO; 4181 return blend_factor; 4182 } 4183 4184 static inline bool is_const_blend(int blend_factor) 4185 { 4186 return (blend_factor == PIPE_BLENDFACTOR_CONST_COLOR || 4187 blend_factor == PIPE_BLENDFACTOR_CONST_ALPHA || 4188 blend_factor == PIPE_BLENDFACTOR_INV_CONST_COLOR || 4189 blend_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA); 4190 } 4191 4192 static void vrend_hw_emit_blend(struct vrend_context *ctx, struct pipe_blend_state *state) 4193 { 4194 if (state->logicop_enable != ctx->sub->hw_blend_state.logicop_enable) { 4195 ctx->sub->hw_blend_state.logicop_enable = state->logicop_enable; 4196 if (vrend_state.use_gles) { 4197 if (state->logicop_enable) { 4198 report_gles_warn(ctx, GLES_WARN_LOGIC_OP, 0); 4199 } 4200 } else if (state->logicop_enable) { 4201 glEnable(GL_COLOR_LOGIC_OP); 4202 glLogicOp(translate_logicop(state->logicop_func)); 4203 } else { 4204 glDisable(GL_COLOR_LOGIC_OP); 4205 } 4206 } 4207 4208 if (state->independent_blend_enable && 4209 has_feature(feat_indep_blend) && 4210 has_feature(feat_indep_blend_func)) { 4211 /* ARB_draw_buffers_blend is required for this */ 4212 int i; 4213 4214 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { 4215 4216 if (state->rt[i].blend_enable) { 4217 bool dual_src = util_blend_state_is_dual(&ctx->sub->blend_state, i); 4218 if (dual_src && !has_feature(feat_dual_src_blend)) { 4219 fprintf(stderr, "dual src blend requested but not supported for rt %d\n", i); 4220 continue; 4221 } 4222 4223 glBlendFuncSeparateiARB(i, translate_blend_factor(state->rt[i].rgb_src_factor), 4224 translate_blend_factor(state->rt[i].rgb_dst_factor), 4225 translate_blend_factor(state->rt[i].alpha_src_factor), 4226 translate_blend_factor(state->rt[i].alpha_dst_factor)); 4227 glBlendEquationSeparateiARB(i, translate_blend_func(state->rt[i].rgb_func), 4228 translate_blend_func(state->rt[i].alpha_func)); 4229 glEnableIndexedEXT(GL_BLEND, i); 4230 } else 4231 glDisableIndexedEXT(GL_BLEND, i); 4232 4233 if (state->rt[i].colormask != ctx->sub->hw_blend_state.rt[i].colormask) { 4234 ctx->sub->hw_blend_state.rt[i].colormask = state->rt[i].colormask; 4235 glColorMaskIndexedEXT(i, state->rt[i].colormask & PIPE_MASK_R ? GL_TRUE : GL_FALSE, 4236 state->rt[i].colormask & PIPE_MASK_G ? GL_TRUE : GL_FALSE, 4237 state->rt[i].colormask & PIPE_MASK_B ? GL_TRUE : GL_FALSE, 4238 state->rt[i].colormask & PIPE_MASK_A ? GL_TRUE : GL_FALSE); 4239 } 4240 } 4241 } else { 4242 if (state->rt[0].blend_enable) { 4243 bool dual_src = util_blend_state_is_dual(&ctx->sub->blend_state, 0); 4244 if (dual_src && !has_feature(feat_dual_src_blend)) { 4245 fprintf(stderr, "dual src blend requested but not supported for rt 0\n"); 4246 } 4247 glBlendFuncSeparate(translate_blend_factor(state->rt[0].rgb_src_factor), 4248 translate_blend_factor(state->rt[0].rgb_dst_factor), 4249 translate_blend_factor(state->rt[0].alpha_src_factor), 4250 translate_blend_factor(state->rt[0].alpha_dst_factor)); 4251 glBlendEquationSeparate(translate_blend_func(state->rt[0].rgb_func), 4252 translate_blend_func(state->rt[0].alpha_func)); 4253 vrend_blend_enable(ctx, true); 4254 } 4255 else 4256 vrend_blend_enable(ctx, false); 4257 4258 if (state->rt[0].colormask != ctx->sub->hw_blend_state.rt[0].colormask) { 4259 int i; 4260 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) 4261 ctx->sub->hw_blend_state.rt[i].colormask = state->rt[i].colormask; 4262 glColorMask(state->rt[0].colormask & PIPE_MASK_R ? GL_TRUE : GL_FALSE, 4263 state->rt[0].colormask & PIPE_MASK_G ? GL_TRUE : GL_FALSE, 4264 state->rt[0].colormask & PIPE_MASK_B ? GL_TRUE : GL_FALSE, 4265 state->rt[0].colormask & PIPE_MASK_A ? GL_TRUE : GL_FALSE); 4266 } 4267 } 4268 ctx->sub->hw_blend_state.independent_blend_enable = state->independent_blend_enable; 4269 4270 if (has_feature(feat_multisample)) { 4271 if (state->alpha_to_coverage) 4272 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); 4273 else 4274 glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); 4275 4276 if (!vrend_state.use_gles) { 4277 if (state->alpha_to_one) 4278 glEnable(GL_SAMPLE_ALPHA_TO_ONE); 4279 else 4280 glDisable(GL_SAMPLE_ALPHA_TO_ONE); 4281 } 4282 } 4283 4284 if (state->dither) 4285 glEnable(GL_DITHER); 4286 else 4287 glDisable(GL_DITHER); 4288 } 4289 4290 /* there are a few reasons we might need to patch the blend state. 4291 a) patching blend factors for dst with no alpha 4292 b) patching colormask/blendcolor/blendfactors for A8/A16 format 4293 emulation using GL_R8/GL_R16. 4294 */ 4295 static void vrend_patch_blend_state(struct vrend_context *ctx) 4296 { 4297 struct pipe_blend_state new_state = ctx->sub->blend_state; 4298 struct pipe_blend_state *state = &ctx->sub->blend_state; 4299 bool swizzle_blend_color = false; 4300 struct pipe_blend_color blend_color = ctx->sub->blend_color; 4301 int i; 4302 4303 if (ctx->sub->nr_cbufs == 0) 4304 return; 4305 4306 for (i = 0; i < (state->independent_blend_enable ? PIPE_MAX_COLOR_BUFS : 1); i++) { 4307 if (i < ctx->sub->nr_cbufs && ctx->sub->surf[i]) { 4308 if (vrend_format_is_emulated_alpha(ctx->sub->surf[i]->format)) { 4309 if (state->rt[i].blend_enable) { 4310 new_state.rt[i].rgb_src_factor = conv_a8_blend(state->rt[i].alpha_src_factor); 4311 new_state.rt[i].rgb_dst_factor = conv_a8_blend(state->rt[i].alpha_dst_factor); 4312 new_state.rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; 4313 new_state.rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 4314 } 4315 new_state.rt[i].colormask = 0; 4316 if (state->rt[i].colormask & PIPE_MASK_A) 4317 new_state.rt[i].colormask |= PIPE_MASK_R; 4318 if (is_const_blend(new_state.rt[i].rgb_src_factor) || 4319 is_const_blend(new_state.rt[i].rgb_dst_factor)) { 4320 swizzle_blend_color = true; 4321 } 4322 } else if (!util_format_has_alpha(ctx->sub->surf[i]->format)) { 4323 if (!(is_dst_blend(state->rt[i].rgb_src_factor) || 4324 is_dst_blend(state->rt[i].rgb_dst_factor) || 4325 is_dst_blend(state->rt[i].alpha_src_factor) || 4326 is_dst_blend(state->rt[i].alpha_dst_factor))) 4327 continue; 4328 new_state.rt[i].rgb_src_factor = conv_dst_blend(state->rt[i].rgb_src_factor); 4329 new_state.rt[i].rgb_dst_factor = conv_dst_blend(state->rt[i].rgb_dst_factor); 4330 new_state.rt[i].alpha_src_factor = conv_dst_blend(state->rt[i].alpha_src_factor); 4331 new_state.rt[i].alpha_dst_factor = conv_dst_blend(state->rt[i].alpha_dst_factor); 4332 } 4333 } 4334 } 4335 4336 vrend_hw_emit_blend(ctx, &new_state); 4337 4338 if (swizzle_blend_color) { 4339 blend_color.color[0] = blend_color.color[3]; 4340 blend_color.color[1] = 0.0f; 4341 blend_color.color[2] = 0.0f; 4342 blend_color.color[3] = 0.0f; 4343 } 4344 4345 glBlendColor(blend_color.color[0], 4346 blend_color.color[1], 4347 blend_color.color[2], 4348 blend_color.color[3]); 4349 } 4350 4351 void vrend_object_bind_blend(struct vrend_context *ctx, 4352 uint32_t handle) 4353 { 4354 struct pipe_blend_state *state; 4355 4356 if (handle == 0) { 4357 memset(&ctx->sub->blend_state, 0, sizeof(ctx->sub->blend_state)); 4358 vrend_blend_enable(ctx, false); 4359 return; 4360 } 4361 state = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_BLEND); 4362 if (!state) { 4363 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); 4364 return; 4365 } 4366 4367 ctx->sub->shader_dirty = true; 4368 ctx->sub->blend_state = *state; 4369 4370 vrend_hw_emit_blend(ctx, &ctx->sub->blend_state); 4371 } 4372 4373 static void vrend_hw_emit_dsa(struct vrend_context *ctx) 4374 { 4375 struct pipe_depth_stencil_alpha_state *state = &ctx->sub->dsa_state; 4376 4377 if (state->depth.enabled) { 4378 vrend_depth_test_enable(ctx, true); 4379 glDepthFunc(GL_NEVER + state->depth.func); 4380 if (state->depth.writemask) 4381 glDepthMask(GL_TRUE); 4382 else 4383 glDepthMask(GL_FALSE); 4384 } else 4385 vrend_depth_test_enable(ctx, false); 4386 4387 if (state->alpha.enabled) { 4388 vrend_alpha_test_enable(ctx, true); 4389 if (!vrend_state.use_core_profile) 4390 glAlphaFunc(GL_NEVER + state->alpha.func, state->alpha.ref_value); 4391 } else 4392 vrend_alpha_test_enable(ctx, false); 4393 4394 4395 } 4396 void vrend_object_bind_dsa(struct vrend_context *ctx, 4397 uint32_t handle) 4398 { 4399 struct pipe_depth_stencil_alpha_state *state; 4400 4401 if (handle == 0) { 4402 memset(&ctx->sub->dsa_state, 0, sizeof(ctx->sub->dsa_state)); 4403 ctx->sub->dsa = NULL; 4404 ctx->sub->stencil_state_dirty = true; 4405 ctx->sub->shader_dirty = true; 4406 vrend_hw_emit_dsa(ctx); 4407 return; 4408 } 4409 4410 state = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_DSA); 4411 if (!state) { 4412 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); 4413 return; 4414 } 4415 4416 if (ctx->sub->dsa != state) { 4417 ctx->sub->stencil_state_dirty = true; 4418 ctx->sub->shader_dirty = true; 4419 } 4420 ctx->sub->dsa_state = *state; 4421 ctx->sub->dsa = state; 4422 4423 vrend_hw_emit_dsa(ctx); 4424 } 4425 4426 static void vrend_update_frontface_state(struct vrend_context *ctx) 4427 { 4428 struct pipe_rasterizer_state *state = &ctx->sub->rs_state; 4429 int front_ccw = state->front_ccw; 4430 4431 front_ccw ^= (ctx->sub->inverted_fbo_content ? 0 : 1); 4432 if (front_ccw) 4433 glFrontFace(GL_CCW); 4434 else 4435 glFrontFace(GL_CW); 4436 } 4437 4438 void vrend_update_stencil_state(struct vrend_context *ctx) 4439 { 4440 struct pipe_depth_stencil_alpha_state *state = ctx->sub->dsa; 4441 int i; 4442 if (!state) 4443 return; 4444 4445 if (!state->stencil[1].enabled) { 4446 if (state->stencil[0].enabled) { 4447 vrend_stencil_test_enable(ctx, true); 4448 4449 glStencilOp(translate_stencil_op(state->stencil[0].fail_op), 4450 translate_stencil_op(state->stencil[0].zfail_op), 4451 translate_stencil_op(state->stencil[0].zpass_op)); 4452 4453 glStencilFunc(GL_NEVER + state->stencil[0].func, 4454 ctx->sub->stencil_refs[0], 4455 state->stencil[0].valuemask); 4456 glStencilMask(state->stencil[0].writemask); 4457 } else 4458 vrend_stencil_test_enable(ctx, false); 4459 } else { 4460 vrend_stencil_test_enable(ctx, true); 4461 4462 for (i = 0; i < 2; i++) { 4463 GLenum face = (i == 1) ? GL_BACK : GL_FRONT; 4464 glStencilOpSeparate(face, 4465 translate_stencil_op(state->stencil[i].fail_op), 4466 translate_stencil_op(state->stencil[i].zfail_op), 4467 translate_stencil_op(state->stencil[i].zpass_op)); 4468 4469 glStencilFuncSeparate(face, GL_NEVER + state->stencil[i].func, 4470 ctx->sub->stencil_refs[i], 4471 state->stencil[i].valuemask); 4472 glStencilMaskSeparate(face, state->stencil[i].writemask); 4473 } 4474 } 4475 ctx->sub->stencil_state_dirty = false; 4476 } 4477 4478 static inline GLenum translate_fill(uint32_t mode) 4479 { 4480 switch (mode) { 4481 case PIPE_POLYGON_MODE_POINT: 4482 return GL_POINT; 4483 case PIPE_POLYGON_MODE_LINE: 4484 return GL_LINE; 4485 case PIPE_POLYGON_MODE_FILL: 4486 return GL_FILL; 4487 default: 4488 assert(0); 4489 return 0; 4490 } 4491 } 4492 4493 static void vrend_hw_emit_rs(struct vrend_context *ctx) 4494 { 4495 struct pipe_rasterizer_state *state = &ctx->sub->rs_state; 4496 int i; 4497 4498 if (vrend_state.use_gles) { 4499 if (!state->depth_clip) { 4500 report_gles_warn(ctx, GLES_WARN_DEPTH_CLIP, 0); 4501 } 4502 } else if (state->depth_clip) { 4503 glDisable(GL_DEPTH_CLAMP); 4504 } else { 4505 glEnable(GL_DEPTH_CLAMP); 4506 } 4507 4508 if (vrend_state.use_gles) { 4509 /* guest send invalid glPointSize parameter */ 4510 if (!state->point_size_per_vertex && 4511 state->point_size != 1.0f && 4512 state->point_size != 0.0f) { 4513 report_gles_warn(ctx, GLES_WARN_POINT_SIZE, 0); 4514 } 4515 } else if (state->point_size_per_vertex) { 4516 glEnable(GL_PROGRAM_POINT_SIZE); 4517 } else { 4518 glDisable(GL_PROGRAM_POINT_SIZE); 4519 if (state->point_size) { 4520 glPointSize(state->point_size); 4521 } 4522 } 4523 4524 /* line_width < 0 is invalid, the guest sometimes forgot to set it. */ 4525 glLineWidth(state->line_width <= 0 ? 1.0f : state->line_width); 4526 4527 if (state->rasterizer_discard != ctx->sub->hw_rs_state.rasterizer_discard) { 4528 ctx->sub->hw_rs_state.rasterizer_discard = state->rasterizer_discard; 4529 if (state->rasterizer_discard) 4530 glEnable(GL_RASTERIZER_DISCARD); 4531 else 4532 glDisable(GL_RASTERIZER_DISCARD); 4533 } 4534 4535 if (vrend_state.use_gles == true) { 4536 if (translate_fill(state->fill_front) != GL_FILL) { 4537 report_gles_warn(ctx, GLES_WARN_POLYGON_MODE, 0); 4538 } 4539 if (translate_fill(state->fill_back) != GL_FILL) { 4540 report_gles_warn(ctx, GLES_WARN_POLYGON_MODE, 0); 4541 } 4542 } else if (vrend_state.use_core_profile == false) { 4543 glPolygonMode(GL_FRONT, translate_fill(state->fill_front)); 4544 glPolygonMode(GL_BACK, translate_fill(state->fill_back)); 4545 } else if (state->fill_front == state->fill_back) { 4546 glPolygonMode(GL_FRONT_AND_BACK, translate_fill(state->fill_front)); 4547 } else 4548 report_core_warn(ctx, CORE_PROFILE_WARN_POLYGON_MODE, 0); 4549 4550 if (state->offset_tri) { 4551 glEnable(GL_POLYGON_OFFSET_FILL); 4552 } else { 4553 glDisable(GL_POLYGON_OFFSET_FILL); 4554 } 4555 4556 if (vrend_state.use_gles) { 4557 if (state->offset_line) { 4558 report_gles_warn(ctx, GLES_WARN_OFFSET_LINE, 0); 4559 } 4560 } else if (state->offset_line) { 4561 glEnable(GL_POLYGON_OFFSET_LINE); 4562 } else { 4563 glDisable(GL_POLYGON_OFFSET_LINE); 4564 } 4565 4566 if (vrend_state.use_gles) { 4567 if (state->offset_point) { 4568 report_gles_warn(ctx, GLES_WARN_OFFSET_POINT, 0); 4569 } 4570 } else if (state->offset_point) { 4571 glEnable(GL_POLYGON_OFFSET_POINT); 4572 } else { 4573 glDisable(GL_POLYGON_OFFSET_POINT); 4574 } 4575 4576 4577 if (state->flatshade != ctx->sub->hw_rs_state.flatshade) { 4578 ctx->sub->hw_rs_state.flatshade = state->flatshade; 4579 if (vrend_state.use_core_profile == false) { 4580 if (state->flatshade) { 4581 glShadeModel(GL_FLAT); 4582 } else { 4583 glShadeModel(GL_SMOOTH); 4584 } 4585 } 4586 } 4587 4588 if (state->flatshade_first != ctx->sub->hw_rs_state.flatshade_first) { 4589 ctx->sub->hw_rs_state.flatshade_first = state->flatshade_first; 4590 if (vrend_state.use_gles) { 4591 if (state->flatshade_first) { 4592 report_gles_warn(ctx, GLES_WARN_FLATSHADE_FIRST, 0); 4593 } 4594 } else if (state->flatshade_first) { 4595 glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT); 4596 } else { 4597 glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT); 4598 } 4599 } 4600 4601 if (!vrend_state.use_gles && has_feature(feat_polygon_offset_clamp)) 4602 glPolygonOffsetClampEXT(state->offset_scale, state->offset_units, state->offset_clamp); 4603 else 4604 glPolygonOffset(state->offset_scale, state->offset_units); 4605 4606 if (vrend_state.use_core_profile == false) { 4607 if (state->poly_stipple_enable) 4608 glEnable(GL_POLYGON_STIPPLE); 4609 else 4610 glDisable(GL_POLYGON_STIPPLE); 4611 } else if (state->poly_stipple_enable) { 4612 if (!ctx->pstip_inited) 4613 vrend_init_pstipple_texture(ctx); 4614 } 4615 4616 if (state->point_quad_rasterization) { 4617 if (vrend_state.use_core_profile == false && 4618 vrend_state.use_gles == false) { 4619 glEnable(GL_POINT_SPRITE); 4620 } 4621 4622 if (vrend_state.use_gles == false) { 4623 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, state->sprite_coord_mode ? GL_UPPER_LEFT : GL_LOWER_LEFT); 4624 } 4625 } else { 4626 if (vrend_state.use_core_profile == false && 4627 vrend_state.use_gles == false) { 4628 glDisable(GL_POINT_SPRITE); 4629 } 4630 } 4631 4632 if (state->cull_face != PIPE_FACE_NONE) { 4633 switch (state->cull_face) { 4634 case PIPE_FACE_FRONT: 4635 glCullFace(GL_FRONT); 4636 break; 4637 case PIPE_FACE_BACK: 4638 glCullFace(GL_BACK); 4639 break; 4640 case PIPE_FACE_FRONT_AND_BACK: 4641 glCullFace(GL_FRONT_AND_BACK); 4642 break; 4643 default: 4644 fprintf(stderr, "unhandled cull-face: %x\n", state->cull_face); 4645 } 4646 glEnable(GL_CULL_FACE); 4647 } else 4648 glDisable(GL_CULL_FACE); 4649 4650 /* two sided lighting handled in shader for core profile */ 4651 if (vrend_state.use_core_profile == false) { 4652 if (state->light_twoside) 4653 glEnable(GL_VERTEX_PROGRAM_TWO_SIDE); 4654 else 4655 glDisable(GL_VERTEX_PROGRAM_TWO_SIDE); 4656 } 4657 4658 if (state->clip_plane_enable != ctx->sub->hw_rs_state.clip_plane_enable) { 4659 ctx->sub->hw_rs_state.clip_plane_enable = state->clip_plane_enable; 4660 for (i = 0; i < 8; i++) { 4661 if (state->clip_plane_enable & (1 << i)) 4662 glEnable(GL_CLIP_PLANE0 + i); 4663 else 4664 glDisable(GL_CLIP_PLANE0 + i); 4665 } 4666 } 4667 if (vrend_state.use_core_profile == false) { 4668 glLineStipple(state->line_stipple_factor, state->line_stipple_pattern); 4669 if (state->line_stipple_enable) 4670 glEnable(GL_LINE_STIPPLE); 4671 else 4672 glDisable(GL_LINE_STIPPLE); 4673 } else if (state->line_stipple_enable) { 4674 if (vrend_state.use_gles) 4675 report_core_warn(ctx, GLES_WARN_STIPPLE, 0); 4676 else 4677 report_core_warn(ctx, CORE_PROFILE_WARN_STIPPLE, 0); 4678 } 4679 4680 4681 if (vrend_state.use_gles) { 4682 if (state->line_smooth) { 4683 report_gles_warn(ctx, GLES_WARN_LINE_SMOOTH, 0); 4684 } 4685 } else if (state->line_smooth) { 4686 glEnable(GL_LINE_SMOOTH); 4687 } else { 4688 glDisable(GL_LINE_SMOOTH); 4689 } 4690 4691 if (vrend_state.use_gles) { 4692 if (state->poly_smooth) { 4693 report_gles_warn(ctx, GLES_WARN_POLY_SMOOTH, 0); 4694 } 4695 } else if (state->poly_smooth) { 4696 glEnable(GL_POLYGON_SMOOTH); 4697 } else { 4698 glDisable(GL_POLYGON_SMOOTH); 4699 } 4700 4701 if (vrend_state.use_core_profile == false) { 4702 if (state->clamp_vertex_color) 4703 glClampColor(GL_CLAMP_VERTEX_COLOR_ARB, GL_TRUE); 4704 else 4705 glClampColor(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE); 4706 4707 if (state->clamp_fragment_color) 4708 glClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_TRUE); 4709 else 4710 glClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE); 4711 } else { 4712 if (state->clamp_vertex_color || state->clamp_fragment_color) 4713 report_core_warn(ctx, CORE_PROFILE_WARN_CLAMP, 0); 4714 } 4715 4716 if (has_feature(feat_multisample)) { 4717 if (has_feature(feat_sample_mask)) { 4718 if (state->multisample) 4719 glEnable(GL_SAMPLE_MASK); 4720 else 4721 glDisable(GL_SAMPLE_MASK); 4722 } 4723 4724 /* GLES doesn't have GL_MULTISAMPLE */ 4725 if (!vrend_state.use_gles) { 4726 if (state->multisample) 4727 glEnable(GL_MULTISAMPLE); 4728 else 4729 glDisable(GL_MULTISAMPLE); 4730 } 4731 4732 if (has_feature(feat_sample_shading)) { 4733 if (state->force_persample_interp) 4734 glEnable(GL_SAMPLE_SHADING); 4735 else 4736 glDisable(GL_SAMPLE_SHADING); 4737 } 4738 } 4739 } 4740 4741 void vrend_object_bind_rasterizer(struct vrend_context *ctx, 4742 uint32_t handle) 4743 { 4744 struct pipe_rasterizer_state *state; 4745 4746 if (handle == 0) { 4747 memset(&ctx->sub->rs_state, 0, sizeof(ctx->sub->rs_state)); 4748 return; 4749 } 4750 4751 state = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_RASTERIZER); 4752 4753 if (!state) { 4754 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handle); 4755 return; 4756 } 4757 4758 ctx->sub->rs_state = *state; 4759 ctx->sub->scissor_state_dirty = (1 << 0); 4760 ctx->sub->shader_dirty = true; 4761 vrend_hw_emit_rs(ctx); 4762 } 4763 4764 void vrend_bind_sampler_states(struct vrend_context *ctx, 4765 uint32_t shader_type, 4766 uint32_t start_slot, 4767 uint32_t num_states, 4768 uint32_t *handles) 4769 { 4770 uint32_t i; 4771 struct vrend_sampler_state *state; 4772 4773 if (shader_type >= PIPE_SHADER_TYPES) { 4774 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, shader_type); 4775 return; 4776 } 4777 4778 if (num_states > PIPE_MAX_SAMPLERS || 4779 start_slot > (PIPE_MAX_SAMPLERS - num_states)) { 4780 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, num_states); 4781 return; 4782 } 4783 4784 ctx->sub->num_sampler_states[shader_type] = num_states; 4785 4786 for (i = 0; i < num_states; i++) { 4787 if (handles[i] == 0) 4788 state = NULL; 4789 else 4790 state = vrend_object_lookup(ctx->sub->object_hash, handles[i], VIRGL_OBJECT_SAMPLER_STATE); 4791 4792 ctx->sub->sampler_state[shader_type][i + start_slot] = state; 4793 } 4794 ctx->sub->sampler_state_dirty = true; 4795 } 4796 4797 static void vrend_apply_sampler_state(struct vrend_context *ctx, 4798 struct vrend_resource *res, 4799 uint32_t shader_type, 4800 int id, 4801 int sampler_id, 4802 uint32_t srgb_decode) 4803 { 4804 struct vrend_texture *tex = (struct vrend_texture *)res; 4805 struct vrend_sampler_state *vstate = ctx->sub->sampler_state[shader_type][id]; 4806 struct pipe_sampler_state *state = &vstate->base; 4807 bool set_all = false; 4808 GLenum target = tex->base.target; 4809 4810 if (!state) { 4811 fprintf(stderr, "cannot find sampler state for %d %d\n", shader_type, id); 4812 return; 4813 } 4814 if (res->base.nr_samples > 1) { 4815 tex->state = *state; 4816 return; 4817 } 4818 4819 if (tex->base.is_buffer) { 4820 tex->state = *state; 4821 return; 4822 } 4823 4824 /* 4825 * If we emulate alpha format with red, we need to tell 4826 * the sampler to use the red channel and not the alpha one 4827 * by swizzling the GL_TEXTURE_BORDER_COLOR parameter. 4828 */ 4829 bool is_emulated_alpha = vrend_format_is_emulated_alpha(res->base.format); 4830 if (has_feature(feat_samplers)) { 4831 if (is_emulated_alpha) { 4832 union pipe_color_union border_color; 4833 border_color = state->border_color; 4834 border_color.ui[0] = border_color.ui[3]; 4835 border_color.ui[3] = 0; 4836 glSamplerParameterIuiv(vstate->id, GL_TEXTURE_BORDER_COLOR, border_color.ui); 4837 } 4838 glBindSampler(sampler_id, vstate->id); 4839 if (has_feature(feat_texture_srgb_decode)) 4840 glSamplerParameteri(vstate->id, GL_TEXTURE_SRGB_DECODE_EXT, 4841 srgb_decode); 4842 return; 4843 } 4844 4845 if (tex->state.max_lod == -1) 4846 set_all = true; 4847 4848 if (tex->state.wrap_s != state->wrap_s || set_all) 4849 glTexParameteri(target, GL_TEXTURE_WRAP_S, convert_wrap(state->wrap_s)); 4850 if (tex->state.wrap_t != state->wrap_t || set_all) 4851 glTexParameteri(target, GL_TEXTURE_WRAP_T, convert_wrap(state->wrap_t)); 4852 if (tex->state.wrap_r != state->wrap_r || set_all) 4853 glTexParameteri(target, GL_TEXTURE_WRAP_R, convert_wrap(state->wrap_r)); 4854 if (tex->state.min_img_filter != state->min_img_filter || 4855 tex->state.min_mip_filter != state->min_mip_filter || set_all) 4856 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, convert_min_filter(state->min_img_filter, state->min_mip_filter)); 4857 if (tex->state.mag_img_filter != state->mag_img_filter || set_all) 4858 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, convert_mag_filter(state->mag_img_filter)); 4859 if (res->target != GL_TEXTURE_RECTANGLE) { 4860 if (tex->state.min_lod != state->min_lod || set_all) 4861 glTexParameterf(target, GL_TEXTURE_MIN_LOD, state->min_lod); 4862 if (tex->state.max_lod != state->max_lod || set_all) 4863 glTexParameterf(target, GL_TEXTURE_MAX_LOD, state->max_lod); 4864 if (tex->state.lod_bias != state->lod_bias || set_all) { 4865 if (vrend_state.use_gles) { 4866 if (state->lod_bias) { 4867 report_gles_warn(ctx, GLES_WARN_LOD_BIAS, 0); 4868 } 4869 } else { 4870 glTexParameterf(target, GL_TEXTURE_LOD_BIAS, state->lod_bias); 4871 } 4872 } 4873 } 4874 4875 if (tex->state.compare_mode != state->compare_mode || set_all) 4876 glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, state->compare_mode ? GL_COMPARE_R_TO_TEXTURE : GL_NONE); 4877 if (tex->state.compare_func != state->compare_func || set_all) 4878 glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_NEVER + state->compare_func); 4879 4880 /* 4881 * Oh this is a fun one. On GLES 2.0 all cubemap MUST NOT be seamless. 4882 * But on GLES 3.0 all cubemaps MUST be seamless. Either way there is no 4883 * way to toggle between the behaviour when running on GLES. And adding 4884 * warnings will spew the logs quite bad. Ignore and hope for the best. 4885 */ 4886 if (!vrend_state.use_gles) { 4887 if (state->seamless_cube_map) { 4888 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); 4889 } else { 4890 glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); 4891 } 4892 } 4893 4894 if (memcmp(&tex->state.border_color, &state->border_color, 16) || set_all || 4895 is_emulated_alpha) { 4896 if (is_emulated_alpha) { 4897 union pipe_color_union border_color; 4898 border_color = state->border_color; 4899 border_color.ui[0] = border_color.ui[3]; 4900 border_color.ui[3] = 0; 4901 glTexParameterIuiv(target, GL_TEXTURE_BORDER_COLOR, border_color.ui); 4902 } else 4903 glTexParameterIuiv(target, GL_TEXTURE_BORDER_COLOR, state->border_color.ui); 4904 } 4905 tex->state = *state; 4906 } 4907 4908 static GLenum tgsitargettogltarget(const enum pipe_texture_target target, int nr_samples) 4909 { 4910 switch(target) { 4911 case PIPE_TEXTURE_1D: 4912 return GL_TEXTURE_1D; 4913 case PIPE_TEXTURE_2D: 4914 return (nr_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; 4915 case PIPE_TEXTURE_3D: 4916 return GL_TEXTURE_3D; 4917 case PIPE_TEXTURE_RECT: 4918 return GL_TEXTURE_RECTANGLE_NV; 4919 case PIPE_TEXTURE_CUBE: 4920 return GL_TEXTURE_CUBE_MAP; 4921 4922 case PIPE_TEXTURE_1D_ARRAY: 4923 return GL_TEXTURE_1D_ARRAY; 4924 case PIPE_TEXTURE_2D_ARRAY: 4925 return (nr_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY; 4926 case PIPE_TEXTURE_CUBE_ARRAY: 4927 return GL_TEXTURE_CUBE_MAP_ARRAY; 4928 case PIPE_BUFFER: 4929 default: 4930 return PIPE_BUFFER; 4931 } 4932 return PIPE_BUFFER; 4933 } 4934 4935 static void vrend_free_sync_thread(void) 4936 { 4937 if (!vrend_state.sync_thread) 4938 return; 4939 4940 pipe_mutex_lock(vrend_state.fence_mutex); 4941 vrend_state.stop_sync_thread = true; 4942 pipe_condvar_signal(vrend_state.fence_cond); 4943 pipe_mutex_unlock(vrend_state.fence_mutex); 4944 4945 pipe_thread_wait(vrend_state.sync_thread); 4946 vrend_state.sync_thread = 0; 4947 4948 pipe_condvar_destroy(vrend_state.fence_cond); 4949 pipe_mutex_destroy(vrend_state.fence_mutex); 4950 } 4951 4952 #ifdef HAVE_EVENTFD 4953 static ssize_t 4954 write_full(int fd, const void *ptr, size_t count) 4955 { 4956 const char *buf = ptr; 4957 ssize_t ret = 0; 4958 ssize_t total = 0; 4959 4960 while (count) { 4961 ret = write(fd, buf, count); 4962 if (ret < 0) { 4963 if (errno == EINTR) 4964 continue; 4965 break; 4966 } 4967 count -= ret; 4968 buf += ret; 4969 total += ret; 4970 } 4971 return total; 4972 } 4973 4974 static void wait_sync(struct vrend_fence *fence) 4975 { 4976 GLenum glret; 4977 ssize_t n; 4978 uint64_t value = 1; 4979 4980 do { 4981 glret = glClientWaitSync(fence->syncobj, 0, 1000000000); 4982 4983 switch (glret) { 4984 case GL_WAIT_FAILED: 4985 fprintf(stderr, "wait sync failed: illegal fence object %p\n", fence->syncobj); 4986 break; 4987 case GL_ALREADY_SIGNALED: 4988 case GL_CONDITION_SATISFIED: 4989 break; 4990 default: 4991 break; 4992 } 4993 } while (glret == GL_TIMEOUT_EXPIRED); 4994 4995 pipe_mutex_lock(vrend_state.fence_mutex); 4996 list_addtail(&fence->fences, &vrend_state.fence_list); 4997 pipe_mutex_unlock(vrend_state.fence_mutex); 4998 4999 n = write_full(vrend_state.eventfd, &value, sizeof(value)); 5000 if (n != sizeof(value)) { 5001 perror("failed to write to eventfd\n"); 5002 } 5003 } 5004 5005 static int thread_sync(UNUSED void *arg) 5006 { 5007 virgl_gl_context gl_context = vrend_state.sync_context; 5008 struct vrend_fence *fence, *stor; 5009 5010 5011 pipe_mutex_lock(vrend_state.fence_mutex); 5012 vrend_clicbs->make_current(0, gl_context); 5013 5014 while (!vrend_state.stop_sync_thread) { 5015 if (LIST_IS_EMPTY(&vrend_state.fence_wait_list) && 5016 pipe_condvar_wait(vrend_state.fence_cond, vrend_state.fence_mutex) != 0) { 5017 fprintf(stderr, "error while waiting on condition\n"); 5018 break; 5019 } 5020 5021 LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_wait_list, fences) { 5022 if (vrend_state.stop_sync_thread) 5023 break; 5024 list_del(&fence->fences); 5025 pipe_mutex_unlock(vrend_state.fence_mutex); 5026 wait_sync(fence); 5027 pipe_mutex_lock(vrend_state.fence_mutex); 5028 } 5029 } 5030 5031 vrend_clicbs->make_current(0, 0); 5032 vrend_clicbs->destroy_gl_context(vrend_state.sync_context); 5033 pipe_mutex_unlock(vrend_state.fence_mutex); 5034 return 0; 5035 } 5036 5037 static void vrend_renderer_use_threaded_sync(void) 5038 { 5039 struct virgl_gl_ctx_param ctx_params; 5040 5041 if (getenv("VIRGL_DISABLE_MT")) 5042 return; 5043 5044 ctx_params.shared = true; 5045 ctx_params.major_ver = vrend_state.gl_major_ver; 5046 ctx_params.minor_ver = vrend_state.gl_minor_ver; 5047 5048 vrend_state.stop_sync_thread = false; 5049 5050 vrend_state.sync_context = vrend_clicbs->create_gl_context(0, &ctx_params); 5051 if (vrend_state.sync_context == NULL) { 5052 fprintf(stderr, "failed to create sync opengl context\n"); 5053 return; 5054 } 5055 5056 vrend_state.eventfd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); 5057 if (vrend_state.eventfd == -1) { 5058 fprintf(stderr, "Failed to create eventfd\n"); 5059 vrend_clicbs->destroy_gl_context(vrend_state.sync_context); 5060 return; 5061 } 5062 5063 pipe_condvar_init(vrend_state.fence_cond); 5064 pipe_mutex_init(vrend_state.fence_mutex); 5065 5066 vrend_state.sync_thread = pipe_thread_create(thread_sync, NULL); 5067 if (!vrend_state.sync_thread) { 5068 close(vrend_state.eventfd); 5069 vrend_state.eventfd = -1; 5070 vrend_clicbs->destroy_gl_context(vrend_state.sync_context); 5071 pipe_condvar_destroy(vrend_state.fence_cond); 5072 pipe_mutex_destroy(vrend_state.fence_mutex); 5073 } 5074 } 5075 #else 5076 static void vrend_renderer_use_threaded_sync(void) 5077 { 5078 } 5079 #endif 5080 5081 static void vrend_debug_cb(UNUSED GLenum source, GLenum type, UNUSED GLuint id, 5082 UNUSED GLenum severity, UNUSED GLsizei length, 5083 UNUSED const GLchar* message, UNUSED const void* userParam) 5084 { 5085 if (type != GL_DEBUG_TYPE_ERROR) { 5086 return; 5087 } 5088 5089 fprintf(stderr, "ERROR: %s\n", message); 5090 } 5091 5092 int vrend_renderer_init(struct vrend_if_cbs *cbs, uint32_t flags) 5093 { 5094 bool gles; 5095 int gl_ver; 5096 virgl_gl_context gl_context; 5097 struct virgl_gl_ctx_param ctx_params; 5098 5099 if (!vrend_state.inited) { 5100 vrend_state.inited = true; 5101 vrend_object_init_resource_table(); 5102 vrend_clicbs = cbs; 5103 } 5104 5105 ctx_params.shared = false; 5106 for (uint32_t i = 0; i < ARRAY_SIZE(gl_versions); i++) { 5107 ctx_params.major_ver = gl_versions[i].major; 5108 ctx_params.minor_ver = gl_versions[i].minor; 5109 5110 gl_context = vrend_clicbs->create_gl_context(0, &ctx_params); 5111 if (gl_context) 5112 break; 5113 } 5114 5115 vrend_clicbs->make_current(0, gl_context); 5116 gl_ver = epoxy_gl_version(); 5117 5118 /* enable error output as early as possible */ 5119 if (vrend_use_debug_cb && epoxy_has_gl_extension("GL_KHR_debug")) { 5120 glDebugMessageCallback(vrend_debug_cb, NULL); 5121 glEnable(GL_DEBUG_OUTPUT); 5122 glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 5123 set_feature(feat_debug_cb); 5124 } 5125 5126 /* make sure you have the latest version of libepoxy */ 5127 gles = epoxy_is_desktop_gl() == 0; 5128 5129 vrend_state.gl_major_ver = gl_ver / 10; 5130 vrend_state.gl_minor_ver = gl_ver % 10; 5131 5132 if (gles) { 5133 fprintf(stderr, "gl_version %d - es profile enabled\n", gl_ver); 5134 vrend_state.use_gles = true; 5135 /* for now, makes the rest of the code use the most GLES 3.x like path */ 5136 vrend_state.use_core_profile = 1; 5137 } else if (gl_ver > 30 && !epoxy_has_gl_extension("GL_ARB_compatibility")) { 5138 fprintf(stderr, "gl_version %d - core profile enabled\n", gl_ver); 5139 vrend_state.use_core_profile = 1; 5140 } else { 5141 fprintf(stderr, "gl_version %d - compat profile\n", gl_ver); 5142 } 5143 5144 init_features(gles ? 0 : gl_ver, 5145 gles ? gl_ver : 0); 5146 5147 glGetIntegerv(GL_MAX_DRAW_BUFFERS, (GLint *) &vrend_state.max_draw_buffers); 5148 5149 if (!has_feature(feat_arb_robustness) && 5150 !has_feature(feat_gles_khr_robustness)) { 5151 fprintf(stderr,"WARNING: running without ARB/KHR robustness in place may crash\n"); 5152 } 5153 5154 /* callbacks for when we are cleaning up the object table */ 5155 vrend_resource_set_destroy_callback(vrend_destroy_resource_object); 5156 vrend_object_set_destroy_callback(VIRGL_OBJECT_QUERY, vrend_destroy_query_object); 5157 vrend_object_set_destroy_callback(VIRGL_OBJECT_SURFACE, vrend_destroy_surface_object); 5158 vrend_object_set_destroy_callback(VIRGL_OBJECT_SHADER, vrend_destroy_shader_object); 5159 vrend_object_set_destroy_callback(VIRGL_OBJECT_SAMPLER_VIEW, vrend_destroy_sampler_view_object); 5160 vrend_object_set_destroy_callback(VIRGL_OBJECT_STREAMOUT_TARGET, vrend_destroy_so_target_object); 5161 vrend_object_set_destroy_callback(VIRGL_OBJECT_SAMPLER_STATE, vrend_destroy_sampler_state_object); 5162 vrend_object_set_destroy_callback(VIRGL_OBJECT_VERTEX_ELEMENTS, vrend_destroy_vertex_elements_object); 5163 5164 /* disable for format testing, spews a lot of errors */ 5165 if (has_feature(feat_debug_cb)) { 5166 glDisable(GL_DEBUG_OUTPUT); 5167 } 5168 5169 vrend_build_format_list_common(); 5170 5171 if (vrend_state.use_gles) { 5172 vrend_build_format_list_gles(); 5173 } else { 5174 vrend_build_format_list_gl(); 5175 } 5176 5177 vrend_check_texture_storage(tex_conv_table); 5178 5179 /* disable for format testing */ 5180 if (has_feature(feat_debug_cb)) { 5181 glDisable(GL_DEBUG_OUTPUT); 5182 } 5183 5184 vrend_clicbs->destroy_gl_context(gl_context); 5185 list_inithead(&vrend_state.fence_list); 5186 list_inithead(&vrend_state.fence_wait_list); 5187 list_inithead(&vrend_state.waiting_query_list); 5188 list_inithead(&vrend_state.active_ctx_list); 5189 /* create 0 context */ 5190 vrend_renderer_context_create_internal(0, 0, NULL); 5191 5192 vrend_state.eventfd = -1; 5193 if (flags & VREND_USE_THREAD_SYNC) { 5194 vrend_renderer_use_threaded_sync(); 5195 } 5196 5197 return 0; 5198 } 5199 5200 void 5201 vrend_renderer_fini(void) 5202 { 5203 if (!vrend_state.inited) 5204 return; 5205 5206 vrend_free_sync_thread(); 5207 if (vrend_state.eventfd != -1) { 5208 close(vrend_state.eventfd); 5209 vrend_state.eventfd = -1; 5210 } 5211 5212 vrend_decode_reset(false); 5213 vrend_object_fini_resource_table(); 5214 vrend_decode_reset(true); 5215 5216 vrend_state.current_ctx = NULL; 5217 vrend_state.current_hw_ctx = NULL; 5218 vrend_state.inited = false; 5219 } 5220 5221 static void vrend_destroy_sub_context(struct vrend_sub_context *sub) 5222 { 5223 int i, j; 5224 struct vrend_streamout_object *obj, *tmp; 5225 5226 if (sub->fb_id) 5227 glDeleteFramebuffers(1, &sub->fb_id); 5228 5229 if (sub->blit_fb_ids[0]) 5230 glDeleteFramebuffers(2, sub->blit_fb_ids); 5231 5232 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 5233 5234 if (!has_feature(feat_gles31_vertex_attrib_binding)) { 5235 while (sub->enabled_attribs_bitmask) { 5236 i = u_bit_scan(&sub->enabled_attribs_bitmask); 5237 5238 glDisableVertexAttribArray(i); 5239 } 5240 glDeleteVertexArrays(1, &sub->vaoid); 5241 } 5242 5243 glBindVertexArray(0); 5244 5245 if (sub->current_so) 5246 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); 5247 5248 LIST_FOR_EACH_ENTRY_SAFE(obj, tmp, &sub->streamout_list, head) { 5249 vrend_destroy_streamout_object(obj); 5250 } 5251 5252 vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_VERTEX], NULL); 5253 vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_FRAGMENT], NULL); 5254 vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_GEOMETRY], NULL); 5255 vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_TESS_CTRL], NULL); 5256 vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_TESS_EVAL], NULL); 5257 vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_COMPUTE], NULL); 5258 5259 vrend_free_programs(sub); 5260 for (i = 0; i < PIPE_SHADER_TYPES; i++) { 5261 free(sub->consts[i].consts); 5262 sub->consts[i].consts = NULL; 5263 5264 for (j = 0; j < PIPE_MAX_SHADER_SAMPLER_VIEWS; j++) { 5265 vrend_sampler_view_reference(&sub->views[i].views[j], NULL); 5266 } 5267 } 5268 5269 if (sub->zsurf) 5270 vrend_surface_reference(&sub->zsurf, NULL); 5271 5272 for (i = 0; i < sub->nr_cbufs; i++) { 5273 if (!sub->surf[i]) 5274 continue; 5275 vrend_surface_reference(&sub->surf[i], NULL); 5276 } 5277 5278 vrend_resource_reference((struct vrend_resource **)&sub->ib.buffer, NULL); 5279 5280 vrend_object_fini_ctx_table(sub->object_hash); 5281 vrend_clicbs->destroy_gl_context(sub->gl_context); 5282 5283 list_del(&sub->head); 5284 FREE(sub); 5285 5286 } 5287 5288 bool vrend_destroy_context(struct vrend_context *ctx) 5289 { 5290 bool switch_0 = (ctx == vrend_state.current_ctx); 5291 struct vrend_context *cur = vrend_state.current_ctx; 5292 struct vrend_sub_context *sub, *tmp; 5293 if (switch_0) { 5294 vrend_state.current_ctx = NULL; 5295 vrend_state.current_hw_ctx = NULL; 5296 } 5297 5298 if (vrend_state.use_core_profile) { 5299 if (ctx->pstip_inited) 5300 glDeleteTextures(1, &ctx->pstipple_tex_id); 5301 ctx->pstip_inited = false; 5302 } 5303 /* reset references on framebuffers */ 5304 vrend_set_framebuffer_state(ctx, 0, NULL, 0); 5305 5306 vrend_set_num_sampler_views(ctx, PIPE_SHADER_VERTEX, 0, 0); 5307 vrend_set_num_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 0); 5308 vrend_set_num_sampler_views(ctx, PIPE_SHADER_GEOMETRY, 0, 0); 5309 vrend_set_num_sampler_views(ctx, PIPE_SHADER_TESS_CTRL, 0, 0); 5310 vrend_set_num_sampler_views(ctx, PIPE_SHADER_TESS_EVAL, 0, 0); 5311 vrend_set_num_sampler_views(ctx, PIPE_SHADER_COMPUTE, 0, 0); 5312 5313 vrend_set_streamout_targets(ctx, 0, 0, NULL); 5314 vrend_set_num_vbo(ctx, 0); 5315 5316 vrend_set_index_buffer(ctx, 0, 0, 0); 5317 5318 vrend_renderer_force_ctx_0(); 5319 LIST_FOR_EACH_ENTRY_SAFE(sub, tmp, &ctx->sub_ctxs, head) 5320 vrend_destroy_sub_context(sub); 5321 5322 vrend_object_fini_ctx_table(ctx->res_hash); 5323 5324 list_del(&ctx->ctx_entry); 5325 5326 FREE(ctx); 5327 5328 if (!switch_0 && cur) 5329 vrend_hw_switch_context(cur, true); 5330 5331 return switch_0; 5332 } 5333 5334 struct vrend_context *vrend_create_context(int id, uint32_t nlen, const char *debug_name) 5335 { 5336 struct vrend_context *grctx = CALLOC_STRUCT(vrend_context); 5337 5338 if (!grctx) 5339 return NULL; 5340 5341 if (nlen && debug_name) { 5342 strncpy(grctx->debug_name, debug_name, 64); 5343 } 5344 5345 grctx->ctx_id = id; 5346 5347 list_inithead(&grctx->sub_ctxs); 5348 list_inithead(&grctx->active_nontimer_query_list); 5349 5350 grctx->res_hash = vrend_object_init_ctx_table(); 5351 5352 grctx->shader_cfg.use_gles = vrend_state.use_gles; 5353 grctx->shader_cfg.use_core_profile = vrend_state.use_core_profile; 5354 grctx->shader_cfg.use_explicit_locations = vrend_state.use_explicit_locations; 5355 grctx->shader_cfg.max_draw_buffers = vrend_state.max_draw_buffers; 5356 vrend_renderer_create_sub_ctx(grctx, 0); 5357 vrend_renderer_set_sub_ctx(grctx, 0); 5358 5359 vrender_get_glsl_version(&grctx->shader_cfg.glsl_version); 5360 5361 list_addtail(&grctx->ctx_entry, &vrend_state.active_ctx_list); 5362 return grctx; 5363 } 5364 5365 int vrend_renderer_resource_attach_iov(int res_handle, struct iovec *iov, 5366 int num_iovs) 5367 { 5368 struct vrend_resource *res; 5369 5370 res = vrend_resource_lookup(res_handle, 0); 5371 if (!res) 5372 return EINVAL; 5373 5374 if (res->iov) 5375 return 0; 5376 5377 /* work out size and max resource size */ 5378 res->iov = iov; 5379 res->num_iovs = num_iovs; 5380 return 0; 5381 } 5382 5383 void vrend_renderer_resource_detach_iov(int res_handle, 5384 struct iovec **iov_p, 5385 int *num_iovs_p) 5386 { 5387 struct vrend_resource *res; 5388 res = vrend_resource_lookup(res_handle, 0); 5389 if (!res) { 5390 return; 5391 } 5392 if (iov_p) 5393 *iov_p = res->iov; 5394 if (num_iovs_p) 5395 *num_iovs_p = res->num_iovs; 5396 5397 res->iov = NULL; 5398 res->num_iovs = 0; 5399 } 5400 5401 static int check_resource_valid(struct vrend_renderer_resource_create_args *args) 5402 { 5403 /* do not accept handle 0 */ 5404 if (args->handle == 0) 5405 return -1; 5406 5407 /* limit the target */ 5408 if (args->target >= PIPE_MAX_TEXTURE_TYPES) 5409 return -1; 5410 5411 if (args->format >= VIRGL_FORMAT_MAX) 5412 return -1; 5413 5414 /* only texture 2d and 2d array can have multiple samples */ 5415 if (args->nr_samples > 1) { 5416 if (!has_feature(feat_texture_multisample)) 5417 return -1; 5418 5419 if (args->target != PIPE_TEXTURE_2D && args->target != PIPE_TEXTURE_2D_ARRAY) 5420 return -1; 5421 /* multisample can't have miplevels */ 5422 if (args->last_level > 0) 5423 return -1; 5424 } 5425 5426 if (args->last_level > 0) { 5427 /* buffer and rect textures can't have mipmaps */ 5428 if (args->target == PIPE_BUFFER || args->target == PIPE_TEXTURE_RECT) 5429 return -1; 5430 if (args->last_level > (floor(log2(MAX2(args->width, args->height))) + 1)) 5431 return -1; 5432 } 5433 if (args->flags != 0 && args->flags != VIRGL_RESOURCE_Y_0_TOP) 5434 return -1; 5435 5436 if (args->flags & VIRGL_RESOURCE_Y_0_TOP) 5437 if (args->target != PIPE_TEXTURE_2D && args->target != PIPE_TEXTURE_RECT) 5438 return -1; 5439 5440 /* array size for array textures only */ 5441 if (args->target == PIPE_TEXTURE_CUBE) { 5442 if (args->array_size != 6) 5443 return -1; 5444 } else if (args->target == PIPE_TEXTURE_CUBE_ARRAY) { 5445 if (!has_feature(feat_cube_map_array)) 5446 return -1; 5447 if (args->array_size % 6) 5448 return -1; 5449 } else if (args->array_size > 1) { 5450 if (args->target != PIPE_TEXTURE_2D_ARRAY && 5451 args->target != PIPE_TEXTURE_1D_ARRAY) 5452 return -1; 5453 5454 if (!has_feature(feat_texture_array)) 5455 return -1; 5456 } 5457 5458 if (args->bind == 0 || 5459 args->bind == VIRGL_BIND_CUSTOM || 5460 args->bind == VIRGL_BIND_INDEX_BUFFER || 5461 args->bind == VIRGL_BIND_STREAM_OUTPUT || 5462 args->bind == VIRGL_BIND_VERTEX_BUFFER || 5463 args->bind == VIRGL_BIND_CONSTANT_BUFFER || 5464 args->bind == VIRGL_BIND_SHADER_BUFFER) { 5465 if (args->target != PIPE_BUFFER) 5466 return -1; 5467 if (args->height != 1 || args->depth != 1) 5468 return -1; 5469 } else { 5470 if (!((args->bind & VIRGL_BIND_SAMPLER_VIEW) || 5471 (args->bind & VIRGL_BIND_DEPTH_STENCIL) || 5472 (args->bind & VIRGL_BIND_RENDER_TARGET) || 5473 (args->bind & VIRGL_BIND_CURSOR))) 5474 return -1; 5475 5476 if (args->target == PIPE_TEXTURE_2D || 5477 args->target == PIPE_TEXTURE_RECT || 5478 args->target == PIPE_TEXTURE_CUBE || 5479 args->target == PIPE_TEXTURE_2D_ARRAY || 5480 args->target == PIPE_TEXTURE_CUBE_ARRAY) { 5481 if (args->depth != 1) 5482 return -1; 5483 } 5484 if (args->target == PIPE_TEXTURE_1D || 5485 args->target == PIPE_TEXTURE_1D_ARRAY) { 5486 if (args->height != 1 || args->depth != 1) 5487 return -1; 5488 } 5489 } 5490 return 0; 5491 } 5492 5493 static void vrend_create_buffer(struct vrend_resource *gr, uint32_t width) 5494 { 5495 glGenBuffersARB(1, &gr->id); 5496 glBindBufferARB(gr->target, gr->id); 5497 glBufferData(gr->target, width, NULL, GL_STREAM_DRAW); 5498 gr->is_buffer = true; 5499 } 5500 5501 static inline void 5502 vrend_renderer_resource_copy_args(struct vrend_renderer_resource_create_args *args, 5503 struct vrend_resource *gr) 5504 { 5505 assert(gr); 5506 assert(args); 5507 5508 gr->handle = args->handle; 5509 gr->base.width0 = args->width; 5510 gr->base.height0 = args->height; 5511 gr->base.depth0 = args->depth; 5512 gr->base.format = args->format; 5513 gr->base.target = args->target; 5514 gr->base.last_level = args->last_level; 5515 gr->base.nr_samples = args->nr_samples; 5516 gr->base.array_size = args->array_size; 5517 } 5518 5519 static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, 5520 void *image_oes) 5521 { 5522 uint level; 5523 GLenum internalformat, glformat, gltype; 5524 struct vrend_texture *gt = (struct vrend_texture *)gr; 5525 struct pipe_resource *pr = &gr->base; 5526 assert(pr->width0 > 0); 5527 5528 bool format_can_texture_storage = has_feature(feat_texture_storage) && 5529 (tex_conv_table[pr->format].bindings & VIRGL_BIND_CAN_TEXTURE_STORAGE); 5530 5531 gr->target = tgsitargettogltarget(pr->target, pr->nr_samples); 5532 5533 /* ugly workaround for texture rectangle missing on GLES */ 5534 if (vrend_state.use_gles && gr->target == GL_TEXTURE_RECTANGLE_NV) { 5535 /* for some guests this is the only usage of rect */ 5536 if (pr->width0 != 1 || pr->height0 != 1) { 5537 report_gles_warn(NULL, GLES_WARN_TEXTURE_RECT, 0); 5538 } 5539 gr->target = GL_TEXTURE_2D; 5540 } 5541 5542 /* fallback for 1D textures */ 5543 if (vrend_state.use_gles && gr->target == GL_TEXTURE_1D) { 5544 gr->target = GL_TEXTURE_2D; 5545 } 5546 5547 /* fallback for 1D array textures */ 5548 if (vrend_state.use_gles && gr->target == GL_TEXTURE_1D_ARRAY) { 5549 gr->target = GL_TEXTURE_2D_ARRAY; 5550 } 5551 5552 glGenTextures(1, &gr->id); 5553 glBindTexture(gr->target, gr->id); 5554 5555 internalformat = tex_conv_table[pr->format].internalformat; 5556 glformat = tex_conv_table[pr->format].glformat; 5557 gltype = tex_conv_table[pr->format].gltype; 5558 5559 if (internalformat == 0) { 5560 fprintf(stderr,"unknown format is %d\n", pr->format); 5561 FREE(gt); 5562 return EINVAL; 5563 } 5564 5565 if (image_oes) { 5566 if (epoxy_has_gl_extension("GL_OES_EGL_image_external")) { 5567 glEGLImageTargetTexture2DOES(gr->target, (GLeglImageOES) image_oes); 5568 } else { 5569 fprintf(stderr, "missing GL_OES_EGL_image_external extension\n"); 5570 FREE(gr); 5571 return EINVAL; 5572 } 5573 } else if (pr->nr_samples > 1) { 5574 if (vrend_state.use_gles || has_feature(feat_texture_storage)) { 5575 if (gr->target == GL_TEXTURE_2D_MULTISAMPLE) { 5576 glTexStorage2DMultisample(gr->target, pr->nr_samples, 5577 internalformat, pr->width0, pr->height0, 5578 GL_TRUE); 5579 } else { 5580 glTexStorage3DMultisample(gr->target, pr->nr_samples, 5581 internalformat, pr->width0, pr->height0, pr->array_size, 5582 GL_TRUE); 5583 } 5584 } else { 5585 if (gr->target == GL_TEXTURE_2D_MULTISAMPLE) { 5586 glTexImage2DMultisample(gr->target, pr->nr_samples, 5587 internalformat, pr->width0, pr->height0, 5588 GL_TRUE); 5589 } else { 5590 glTexImage3DMultisample(gr->target, pr->nr_samples, 5591 internalformat, pr->width0, pr->height0, pr->array_size, 5592 GL_TRUE); 5593 } 5594 } 5595 } else if (gr->target == GL_TEXTURE_CUBE_MAP) { 5596 int i; 5597 if (format_can_texture_storage) 5598 glTexStorage2D(GL_TEXTURE_CUBE_MAP, pr->last_level + 1, internalformat, pr->width0, pr->height0); 5599 else { 5600 for (i = 0; i < 6; i++) { 5601 GLenum ctarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i; 5602 for (level = 0; level <= pr->last_level; level++) { 5603 unsigned mwidth = u_minify(pr->width0, level); 5604 unsigned mheight = u_minify(pr->height0, level); 5605 5606 glTexImage2D(ctarget, level, internalformat, mwidth, mheight, 0, glformat, 5607 gltype, NULL); 5608 } 5609 } 5610 } 5611 } else if (gr->target == GL_TEXTURE_3D || 5612 gr->target == GL_TEXTURE_2D_ARRAY || 5613 gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) { 5614 if (format_can_texture_storage) { 5615 unsigned depth_param = (gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) ? 5616 pr->array_size : pr->depth0; 5617 glTexStorage3D(gr->target, pr->last_level + 1, internalformat, pr->width0, pr->height0, depth_param); 5618 } else { 5619 for (level = 0; level <= pr->last_level; level++) { 5620 unsigned depth_param = (gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) ? 5621 pr->array_size : u_minify(pr->depth0, level); 5622 unsigned mwidth = u_minify(pr->width0, level); 5623 unsigned mheight = u_minify(pr->height0, level); 5624 glTexImage3D(gr->target, level, internalformat, mwidth, mheight, 5625 depth_param, 0, glformat, gltype, NULL); 5626 } 5627 } 5628 } else if (gr->target == GL_TEXTURE_1D && vrend_state.use_gles) { 5629 report_gles_missing_func(NULL, "glTexImage1D"); 5630 } else if (gr->target == GL_TEXTURE_1D) { 5631 if (format_can_texture_storage) { 5632 glTexStorage1D(gr->target, pr->last_level + 1, internalformat, pr->width0); 5633 } else { 5634 for (level = 0; level <= pr->last_level; level++) { 5635 unsigned mwidth = u_minify(pr->width0, level); 5636 glTexImage1D(gr->target, level, internalformat, mwidth, 0, 5637 glformat, gltype, NULL); 5638 } 5639 } 5640 } else { 5641 if (format_can_texture_storage) 5642 glTexStorage2D(gr->target, pr->last_level + 1, internalformat, pr->width0, 5643 gr->target == GL_TEXTURE_1D_ARRAY ? pr->array_size : pr->height0); 5644 else { 5645 for (level = 0; level <= pr->last_level; level++) { 5646 unsigned mwidth = u_minify(pr->width0, level); 5647 unsigned mheight = u_minify(pr->height0, level); 5648 glTexImage2D(gr->target, level, internalformat, mwidth, 5649 gr->target == GL_TEXTURE_1D_ARRAY ? pr->array_size : mheight, 5650 0, glformat, gltype, NULL); 5651 } 5652 } 5653 } 5654 5655 if (!format_can_texture_storage) { 5656 glTexParameteri(gr->target, GL_TEXTURE_BASE_LEVEL, 0); 5657 glTexParameteri(gr->target, GL_TEXTURE_MAX_LEVEL, pr->last_level); 5658 } 5659 5660 gt->state.max_lod = -1; 5661 return 0; 5662 } 5663 5664 int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *args, struct iovec *iov, uint32_t num_iovs, void *image_oes) 5665 { 5666 struct vrend_resource *gr; 5667 int ret; 5668 5669 ret = check_resource_valid(args); 5670 if (ret) 5671 return EINVAL; 5672 5673 gr = (struct vrend_resource *)CALLOC_STRUCT(vrend_texture); 5674 if (!gr) 5675 return ENOMEM; 5676 5677 vrend_renderer_resource_copy_args(args, gr); 5678 gr->iov = iov; 5679 gr->num_iovs = num_iovs; 5680 5681 if (args->flags & VIRGL_RESOURCE_Y_0_TOP) 5682 gr->y_0_top = true; 5683 5684 pipe_reference_init(&gr->base.reference, 1); 5685 5686 if (args->bind == VIRGL_BIND_CUSTOM) { 5687 /* custom should only be for buffers */ 5688 gr->ptr = malloc(args->width); 5689 if (!gr->ptr) { 5690 FREE(gr); 5691 return ENOMEM; 5692 } 5693 } else if (args->bind == VIRGL_BIND_INDEX_BUFFER) { 5694 gr->target = GL_ELEMENT_ARRAY_BUFFER_ARB; 5695 vrend_create_buffer(gr, args->width); 5696 } else if (args->bind == VIRGL_BIND_STREAM_OUTPUT) { 5697 gr->target = GL_TRANSFORM_FEEDBACK_BUFFER; 5698 vrend_create_buffer(gr, args->width); 5699 } else if (args->bind == VIRGL_BIND_VERTEX_BUFFER) { 5700 gr->target = GL_ARRAY_BUFFER_ARB; 5701 vrend_create_buffer(gr, args->width); 5702 } else if (args->bind == VIRGL_BIND_CONSTANT_BUFFER) { 5703 gr->target = GL_UNIFORM_BUFFER; 5704 vrend_create_buffer(gr, args->width); 5705 } else if (args->target == PIPE_BUFFER && (args->bind == 0 || args->bind == VIRGL_BIND_SHADER_BUFFER)) { 5706 gr->target = GL_ARRAY_BUFFER_ARB; 5707 vrend_create_buffer(gr, args->width); 5708 } else if (args->target == PIPE_BUFFER && (args->bind & VIRGL_BIND_SAMPLER_VIEW)) { 5709 /* 5710 * On Desktop we use GL_ARB_texture_buffer_object on GLES we use 5711 * GL_EXT_texture_buffer (it is in the ANDRIOD extension pack). 5712 */ 5713 #if GL_TEXTURE_BUFFER != GL_TEXTURE_BUFFER_EXT 5714 #error "GL_TEXTURE_BUFFER enums differ, they shouldn't." 5715 #endif 5716 5717 /* need to check GL version here */ 5718 if (has_feature(feat_arb_or_gles_ext_texture_buffer)) { 5719 gr->target = GL_TEXTURE_BUFFER; 5720 } else { 5721 gr->target = GL_PIXEL_PACK_BUFFER_ARB; 5722 } 5723 vrend_create_buffer(gr, args->width); 5724 } else { 5725 int r = vrend_renderer_resource_allocate_texture(gr, image_oes); 5726 if (r) 5727 return r; 5728 } 5729 5730 ret = vrend_resource_insert(gr, args->handle); 5731 if (ret == 0) { 5732 vrend_renderer_resource_destroy(gr, true); 5733 return ENOMEM; 5734 } 5735 return 0; 5736 } 5737 5738 void vrend_renderer_resource_destroy(struct vrend_resource *res, bool remove) 5739 { 5740 if (res->readback_fb_id) 5741 glDeleteFramebuffers(1, &res->readback_fb_id); 5742 5743 if (res->ptr) 5744 free(res->ptr); 5745 if (res->id) { 5746 if (res->is_buffer) { 5747 glDeleteBuffers(1, &res->id); 5748 if (res->tbo_tex_id) 5749 glDeleteTextures(1, &res->tbo_tex_id); 5750 } else 5751 glDeleteTextures(1, &res->id); 5752 } 5753 5754 if (res->handle && remove) 5755 vrend_resource_remove(res->handle); 5756 free(res); 5757 } 5758 5759 static void vrend_destroy_resource_object(void *obj_ptr) 5760 { 5761 struct vrend_resource *res = obj_ptr; 5762 5763 if (pipe_reference(&res->base.reference, NULL)) 5764 vrend_renderer_resource_destroy(res, false); 5765 } 5766 5767 void vrend_renderer_resource_unref(uint32_t res_handle) 5768 { 5769 struct vrend_resource *res; 5770 struct vrend_context *ctx; 5771 5772 res = vrend_resource_lookup(res_handle, 0); 5773 if (!res) 5774 return; 5775 5776 /* find in all contexts and detach also */ 5777 5778 /* remove from any contexts */ 5779 LIST_FOR_EACH_ENTRY(ctx, &vrend_state.active_ctx_list, ctx_entry) { 5780 vrend_renderer_detach_res_ctx_p(ctx, res->handle); 5781 } 5782 5783 vrend_resource_remove(res->handle); 5784 } 5785 5786 static int use_sub_data = 0; 5787 struct virgl_sub_upload_data { 5788 GLenum target; 5789 struct pipe_box *box; 5790 }; 5791 5792 static void iov_buffer_upload(void *cookie, uint32_t doff, void *src, int len) 5793 { 5794 struct virgl_sub_upload_data *d = cookie; 5795 glBufferSubData(d->target, d->box->x + doff, len, src); 5796 } 5797 5798 static void vrend_scale_depth(void *ptr, int size, float scale_val) 5799 { 5800 GLuint *ival = ptr; 5801 const GLfloat myscale = 1.0f / 0xffffff; 5802 int i; 5803 for (i = 0; i < size / 4; i++) { 5804 GLuint value = ival[i]; 5805 GLfloat d = ((float)(value >> 8) * myscale) * scale_val; 5806 d = CLAMP(d, 0.0F, 1.0F); 5807 ival[i] = (int)(d / myscale) << 8; 5808 } 5809 } 5810 5811 static void read_transfer_data(struct pipe_resource *res, 5812 struct iovec *iov, 5813 unsigned int num_iovs, 5814 char *data, 5815 uint32_t src_stride, 5816 struct pipe_box *box, 5817 uint32_t level, 5818 uint64_t offset, 5819 bool invert) 5820 { 5821 int blsize = util_format_get_blocksize(res->format); 5822 uint32_t size = vrend_get_iovec_size(iov, num_iovs); 5823 uint32_t send_size = util_format_get_nblocks(res->format, box->width, 5824 box->height) * blsize * box->depth; 5825 uint32_t bwx = util_format_get_nblocksx(res->format, box->width) * blsize; 5826 int32_t bh = util_format_get_nblocksy(res->format, box->height); 5827 int d, h; 5828 5829 if ((send_size == size || bh == 1) && !invert && box->depth == 1) 5830 vrend_read_from_iovec(iov, num_iovs, offset, data, send_size); 5831 else { 5832 if (invert) { 5833 for (d = 0; d < box->depth; d++) { 5834 uint32_t myoffset = offset + d * src_stride * u_minify(res->height0, level); 5835 for (h = bh - 1; h >= 0; h--) { 5836 void *ptr = data + (h * bwx) + d * (bh * bwx); 5837 vrend_read_from_iovec(iov, num_iovs, myoffset, ptr, bwx); 5838 myoffset += src_stride; 5839 } 5840 } 5841 } else { 5842 for (d = 0; d < box->depth; d++) { 5843 uint32_t myoffset = offset + d * src_stride * u_minify(res->height0, level); 5844 for (h = 0; h < bh; h++) { 5845 void *ptr = data + (h * bwx) + d * (bh * bwx); 5846 vrend_read_from_iovec(iov, num_iovs, myoffset, ptr, bwx); 5847 myoffset += src_stride; 5848 } 5849 } 5850 } 5851 } 5852 } 5853 5854 static void write_transfer_data(struct pipe_resource *res, 5855 struct iovec *iov, 5856 unsigned num_iovs, 5857 char *data, 5858 uint32_t dst_stride, 5859 struct pipe_box *box, 5860 uint32_t level, 5861 uint64_t offset, 5862 bool invert) 5863 { 5864 int blsize = util_format_get_blocksize(res->format); 5865 uint32_t size = vrend_get_iovec_size(iov, num_iovs); 5866 uint32_t send_size = util_format_get_nblocks(res->format, box->width, 5867 box->height) * blsize * box->depth; 5868 uint32_t bwx = util_format_get_nblocksx(res->format, box->width) * blsize; 5869 int32_t bh = util_format_get_nblocksy(res->format, box->height); 5870 int d, h; 5871 uint32_t stride = dst_stride ? dst_stride : util_format_get_nblocksx(res->format, u_minify(res->width0, level)) * blsize; 5872 5873 if ((send_size == size || bh == 1) && !invert && box->depth == 1) { 5874 vrend_write_to_iovec(iov, num_iovs, offset, data, send_size); 5875 } else if (invert) { 5876 for (d = 0; d < box->depth; d++) { 5877 uint32_t myoffset = offset + d * stride * u_minify(res->height0, level); 5878 for (h = bh - 1; h >= 0; h--) { 5879 void *ptr = data + (h * bwx) + d * (bh * bwx); 5880 vrend_write_to_iovec(iov, num_iovs, myoffset, ptr, bwx); 5881 myoffset += stride; 5882 } 5883 } 5884 } else { 5885 for (d = 0; d < box->depth; d++) { 5886 uint32_t myoffset = offset + d * stride * u_minify(res->height0, level); 5887 for (h = 0; h < bh; h++) { 5888 void *ptr = data + (h * bwx) + d * (bh * bwx); 5889 vrend_write_to_iovec(iov, num_iovs, myoffset, ptr, bwx); 5890 myoffset += stride; 5891 } 5892 } 5893 } 5894 } 5895 5896 static bool check_transfer_bounds(struct vrend_resource *res, 5897 const struct vrend_transfer_info *info) 5898 { 5899 int lwidth, lheight; 5900 5901 /* check mipmap level is in bounds */ 5902 if (info->level > res->base.last_level) 5903 return false; 5904 if (info->box->x < 0 || info->box->y < 0) 5905 return false; 5906 /* these will catch bad y/z/w/d with 1D textures etc */ 5907 lwidth = u_minify(res->base.width0, info->level); 5908 if (info->box->width > lwidth) 5909 return false; 5910 if (info->box->x > lwidth) 5911 return false; 5912 if (info->box->width + info->box->x > lwidth) 5913 return false; 5914 5915 lheight = u_minify(res->base.height0, info->level); 5916 if (info->box->height > lheight) 5917 return false; 5918 if (info->box->y > lheight) 5919 return false; 5920 if (info->box->height + info->box->y > lheight) 5921 return false; 5922 5923 if (res->base.target == PIPE_TEXTURE_3D) { 5924 int ldepth = u_minify(res->base.depth0, info->level); 5925 if (info->box->depth > ldepth) 5926 return false; 5927 if (info->box->z > ldepth) 5928 return false; 5929 if (info->box->z + info->box->depth > ldepth) 5930 return false; 5931 } else { 5932 if (info->box->depth > (int)res->base.array_size) 5933 return false; 5934 if (info->box->z > (int)res->base.array_size) 5935 return false; 5936 if (info->box->z + info->box->depth > (int)res->base.array_size) 5937 return false; 5938 } 5939 5940 return true; 5941 } 5942 5943 static bool check_iov_bounds(struct vrend_resource *res, 5944 const struct vrend_transfer_info *info, 5945 struct iovec *iov, int num_iovs) 5946 { 5947 GLuint send_size; 5948 GLuint iovsize = vrend_get_iovec_size(iov, num_iovs); 5949 GLuint valid_stride, valid_layer_stride; 5950 5951 /* validate the send size */ 5952 valid_stride = util_format_get_stride(res->base.format, info->box->width); 5953 if (info->stride) { 5954 /* only validate passed in stride for boxes with height */ 5955 if (info->box->height > 1) { 5956 if (info->stride < valid_stride) 5957 return false; 5958 valid_stride = info->stride; 5959 } 5960 } 5961 5962 valid_layer_stride = util_format_get_2d_size(res->base.format, valid_stride, 5963 info->box->height); 5964 5965 /* layer stride only makes sense for 3d,cube and arrays */ 5966 if (info->layer_stride) { 5967 if ((res->base.target != PIPE_TEXTURE_3D && 5968 res->base.target != PIPE_TEXTURE_CUBE && 5969 res->base.target != PIPE_TEXTURE_1D_ARRAY && 5970 res->base.target != PIPE_TEXTURE_2D_ARRAY && 5971 res->base.target != PIPE_TEXTURE_CUBE_ARRAY)) 5972 return false; 5973 5974 /* only validate passed in layer_stride for boxes with depth */ 5975 if (info->box->depth > 1) { 5976 if (info->layer_stride < valid_layer_stride) 5977 return false; 5978 valid_layer_stride = info->layer_stride; 5979 } 5980 } 5981 5982 send_size = valid_layer_stride * info->box->depth; 5983 if (iovsize < info->offset) 5984 return false; 5985 if (iovsize < send_size) 5986 return false; 5987 if (iovsize < info->offset + send_size) 5988 return false; 5989 5990 return true; 5991 } 5992 5993 static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx, 5994 struct vrend_resource *res, 5995 struct iovec *iov, int num_iovs, 5996 const struct vrend_transfer_info *info) 5997 { 5998 void *data; 5999 6000 if (res->target == 0 && res->ptr) { 6001 vrend_read_from_iovec(iov, num_iovs, info->offset, res->ptr + info->box->x, info->box->width); 6002 return 0; 6003 } 6004 if (res->target == GL_TRANSFORM_FEEDBACK_BUFFER || 6005 res->target == GL_ELEMENT_ARRAY_BUFFER_ARB || 6006 res->target == GL_ARRAY_BUFFER_ARB || 6007 res->target == GL_TEXTURE_BUFFER || 6008 res->target == GL_UNIFORM_BUFFER) { 6009 struct virgl_sub_upload_data d; 6010 d.box = info->box; 6011 d.target = res->target; 6012 6013 glBindBufferARB(res->target, res->id); 6014 if (use_sub_data == 1) { 6015 vrend_read_from_iovec_cb(iov, num_iovs, info->offset, info->box->width, &iov_buffer_upload, &d); 6016 } else { 6017 data = glMapBufferRange(res->target, info->box->x, info->box->width, GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_WRITE_BIT); 6018 if (data == NULL) { 6019 fprintf(stderr,"map failed for element buffer\n"); 6020 vrend_read_from_iovec_cb(iov, num_iovs, info->offset, info->box->width, &iov_buffer_upload, &d); 6021 } else { 6022 vrend_read_from_iovec(iov, num_iovs, info->offset, data, info->box->width); 6023 glUnmapBuffer(res->target); 6024 } 6025 } 6026 } else { 6027 GLenum glformat; 6028 GLenum gltype; 6029 int need_temp = 0; 6030 int elsize = util_format_get_blocksize(res->base.format); 6031 int x = 0, y = 0; 6032 bool compressed; 6033 bool invert = false; 6034 float depth_scale; 6035 GLuint send_size = 0; 6036 uint32_t stride = info->stride; 6037 6038 vrend_use_program(ctx, 0); 6039 6040 if (!stride) 6041 stride = util_format_get_nblocksx(res->base.format, u_minify(res->base.width0, info->level)) * elsize; 6042 6043 compressed = util_format_is_compressed(res->base.format); 6044 if (num_iovs > 1 || compressed) { 6045 need_temp = true; 6046 } 6047 6048 if (vrend_state.use_core_profile == true && (res->y_0_top || (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM))) { 6049 need_temp = true; 6050 if (res->y_0_top) 6051 invert = true; 6052 } 6053 6054 if (need_temp) { 6055 send_size = util_format_get_nblocks(res->base.format, info->box->width, 6056 info->box->height) * elsize * info->box->depth; 6057 data = malloc(send_size); 6058 if (!data) 6059 return ENOMEM; 6060 read_transfer_data(&res->base, iov, num_iovs, data, stride, 6061 info->box, info->level, info->offset, invert); 6062 } else { 6063 data = (char*)iov[0].iov_base + info->offset; 6064 } 6065 6066 if (stride && !need_temp) { 6067 glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / elsize); 6068 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, u_minify(res->base.height0, info->level)); 6069 } else 6070 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 6071 6072 switch (elsize) { 6073 case 1: 6074 case 3: 6075 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 6076 break; 6077 case 2: 6078 case 6: 6079 glPixelStorei(GL_UNPACK_ALIGNMENT, 2); 6080 break; 6081 case 4: 6082 default: 6083 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 6084 break; 6085 case 8: 6086 glPixelStorei(GL_UNPACK_ALIGNMENT, 8); 6087 break; 6088 } 6089 6090 glformat = tex_conv_table[res->base.format].glformat; 6091 gltype = tex_conv_table[res->base.format].gltype; 6092 6093 if ((!vrend_state.use_core_profile) && (res->y_0_top)) { 6094 GLuint buffers; 6095 6096 if (res->readback_fb_id == 0 || (int)res->readback_fb_level != info->level) { 6097 GLuint fb_id; 6098 if (res->readback_fb_id) 6099 glDeleteFramebuffers(1, &res->readback_fb_id); 6100 6101 glGenFramebuffers(1, &fb_id); 6102 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_id); 6103 vrend_fb_bind_texture(res, 0, info->level, 0); 6104 6105 res->readback_fb_id = fb_id; 6106 res->readback_fb_level = info->level; 6107 } else { 6108 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, res->readback_fb_id); 6109 } 6110 6111 buffers = GL_COLOR_ATTACHMENT0_EXT; 6112 glDrawBuffers(1, &buffers); 6113 vrend_blend_enable(ctx, false); 6114 vrend_depth_test_enable(ctx, false); 6115 vrend_alpha_test_enable(ctx, false); 6116 vrend_stencil_test_enable(ctx, false); 6117 glPixelZoom(1.0f, res->y_0_top ? -1.0f : 1.0f); 6118 glWindowPos2i(info->box->x, res->y_0_top ? (int)res->base.height0 - info->box->y : info->box->y); 6119 glDrawPixels(info->box->width, info->box->height, glformat, gltype, 6120 data); 6121 } else { 6122 uint32_t comp_size; 6123 glBindTexture(res->target, res->id); 6124 6125 if (compressed) { 6126 glformat = tex_conv_table[res->base.format].internalformat; 6127 comp_size = util_format_get_nblocks(res->base.format, info->box->width, 6128 info->box->height) * util_format_get_blocksize(res->base.format); 6129 } 6130 6131 if (glformat == 0) { 6132 glformat = GL_BGRA; 6133 gltype = GL_UNSIGNED_BYTE; 6134 } 6135 6136 x = info->box->x; 6137 y = invert ? (int)res->base.height0 - info->box->y - info->box->height : info->box->y; 6138 6139 6140 /* mipmaps are usually passed in one iov, and we need to keep the offset 6141 * into the data in case we want to read back the data of a surface 6142 * that can not be rendered. Since we can not assume that the whole texture 6143 * is filled, we evaluate the offset for origin (0,0,0). Since it is also 6144 * possible that a resource is reused and resized update the offset every time. 6145 */ 6146 if (info->level < VR_MAX_TEXTURE_2D_LEVELS) { 6147 int64_t level_height = u_minify(res->base.height0, info->level); 6148 res->mipmap_offsets[info->level] = info->offset - 6149 ((info->box->z * level_height + y) * stride + x * elsize); 6150 } 6151 6152 if (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) { 6153 /* we get values from the guest as 24-bit scaled integers 6154 but we give them to the host GL and it interprets them 6155 as 32-bit scaled integers, so we need to scale them here */ 6156 depth_scale = 256.0; 6157 if (!vrend_state.use_core_profile) 6158 glPixelTransferf(GL_DEPTH_SCALE, depth_scale); 6159 else 6160 vrend_scale_depth(data, send_size, depth_scale); 6161 } 6162 if (res->target == GL_TEXTURE_CUBE_MAP) { 6163 GLenum ctarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info->box->z; 6164 if (compressed) { 6165 glCompressedTexSubImage2D(ctarget, info->level, x, y, 6166 info->box->width, info->box->height, 6167 glformat, comp_size, data); 6168 } else { 6169 glTexSubImage2D(ctarget, info->level, x, y, info->box->width, info->box->height, 6170 glformat, gltype, data); 6171 } 6172 } else if (res->target == GL_TEXTURE_3D || res->target == GL_TEXTURE_2D_ARRAY || res->target == GL_TEXTURE_CUBE_MAP_ARRAY) { 6173 if (compressed) { 6174 glCompressedTexSubImage3D(res->target, info->level, x, y, info->box->z, 6175 info->box->width, info->box->height, info->box->depth, 6176 glformat, comp_size, data); 6177 } else { 6178 glTexSubImage3D(res->target, info->level, x, y, info->box->z, 6179 info->box->width, info->box->height, info->box->depth, 6180 glformat, gltype, data); 6181 } 6182 } else if (res->target == GL_TEXTURE_1D) { 6183 if (vrend_state.use_gles) { 6184 /* Covers both compressed and none compressed. */ 6185 report_gles_missing_func(ctx, "gl[Compressed]TexSubImage1D"); 6186 } else if (compressed) { 6187 glCompressedTexSubImage1D(res->target, info->level, info->box->x, 6188 info->box->width, 6189 glformat, comp_size, data); 6190 } else { 6191 glTexSubImage1D(res->target, info->level, info->box->x, info->box->width, 6192 glformat, gltype, data); 6193 } 6194 } else { 6195 if (compressed) { 6196 glCompressedTexSubImage2D(res->target, info->level, x, res->target == GL_TEXTURE_1D_ARRAY ? info->box->z : y, 6197 info->box->width, info->box->height, 6198 glformat, comp_size, data); 6199 } else { 6200 glTexSubImage2D(res->target, info->level, x, res->target == GL_TEXTURE_1D_ARRAY ? info->box->z : y, 6201 info->box->width, 6202 res->target == GL_TEXTURE_1D_ARRAY ? info->box->depth : info->box->height, 6203 glformat, gltype, data); 6204 } 6205 } 6206 if (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) { 6207 if (!vrend_state.use_core_profile) 6208 glPixelTransferf(GL_DEPTH_SCALE, 1.0); 6209 } 6210 } 6211 6212 if (stride && !need_temp) { 6213 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 6214 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); 6215 } 6216 6217 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 6218 6219 if (need_temp) 6220 free(data); 6221 } 6222 return 0; 6223 } 6224 6225 static uint32_t vrend_get_texture_depth(struct vrend_resource *res, uint32_t level) 6226 { 6227 uint32_t depth = 1; 6228 if (res->target == GL_TEXTURE_3D) 6229 depth = u_minify(res->base.depth0, level); 6230 else if (res->target == GL_TEXTURE_1D_ARRAY || res->target == GL_TEXTURE_2D_ARRAY || 6231 res->target == GL_TEXTURE_CUBE_MAP || res->target == GL_TEXTURE_CUBE_MAP_ARRAY) 6232 depth = res->base.array_size; 6233 6234 return depth; 6235 } 6236 6237 static int vrend_transfer_send_getteximage(struct vrend_context *ctx, 6238 struct vrend_resource *res, 6239 struct iovec *iov, int num_iovs, 6240 const struct vrend_transfer_info *info) 6241 { 6242 GLenum format, type; 6243 uint32_t tex_size; 6244 char *data; 6245 int elsize = util_format_get_blocksize(res->base.format); 6246 int compressed = util_format_is_compressed(res->base.format); 6247 GLenum target; 6248 uint32_t send_offset = 0; 6249 format = tex_conv_table[res->base.format].glformat; 6250 type = tex_conv_table[res->base.format].gltype; 6251 6252 if (compressed) 6253 format = tex_conv_table[res->base.format].internalformat; 6254 6255 tex_size = util_format_get_nblocks(res->base.format, u_minify(res->base.width0, info->level), u_minify(res->base.height0, info->level)) * 6256 util_format_get_blocksize(res->base.format) * vrend_get_texture_depth(res, info->level); 6257 6258 if (info->box->z && res->target != GL_TEXTURE_CUBE_MAP) { 6259 send_offset = util_format_get_nblocks(res->base.format, u_minify(res->base.width0, info->level), u_minify(res->base.height0, info->level)) * util_format_get_blocksize(res->base.format) * info->box->z; 6260 } 6261 6262 data = malloc(tex_size); 6263 if (!data) 6264 return ENOMEM; 6265 6266 switch (elsize) { 6267 case 1: 6268 glPixelStorei(GL_PACK_ALIGNMENT, 1); 6269 break; 6270 case 2: 6271 glPixelStorei(GL_PACK_ALIGNMENT, 2); 6272 break; 6273 case 4: 6274 default: 6275 glPixelStorei(GL_PACK_ALIGNMENT, 4); 6276 break; 6277 case 8: 6278 glPixelStorei(GL_PACK_ALIGNMENT, 8); 6279 break; 6280 } 6281 6282 glBindTexture(res->target, res->id); 6283 if (res->target == GL_TEXTURE_CUBE_MAP) { 6284 target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info->box->z; 6285 } else 6286 target = res->target; 6287 6288 if (compressed) { 6289 if (has_feature(feat_arb_robustness)) { 6290 glGetnCompressedTexImageARB(target, info->level, tex_size, data); 6291 } else if (vrend_state.use_gles) { 6292 report_gles_missing_func(ctx, "glGetCompressedTexImage"); 6293 } else { 6294 glGetCompressedTexImage(target, info->level, data); 6295 } 6296 } else { 6297 if (has_feature(feat_arb_robustness)) { 6298 glGetnTexImageARB(target, info->level, format, type, tex_size, data); 6299 } else if (vrend_state.use_gles) { 6300 report_gles_missing_func(ctx, "glGetTexImage"); 6301 } else { 6302 glGetTexImage(target, info->level, format, type, data); 6303 } 6304 } 6305 6306 glPixelStorei(GL_PACK_ALIGNMENT, 4); 6307 6308 write_transfer_data(&res->base, iov, num_iovs, data + send_offset, 6309 info->stride, info->box, info->level, info->offset, 6310 false); 6311 free(data); 6312 return 0; 6313 } 6314 6315 static int vrend_transfer_send_readpixels(struct vrend_context *ctx, 6316 struct vrend_resource *res, 6317 struct iovec *iov, int num_iovs, 6318 const struct vrend_transfer_info *info) 6319 { 6320 char *myptr = (char*)iov[0].iov_base + info->offset; 6321 int need_temp = 0; 6322 GLuint fb_id; 6323 char *data; 6324 bool actually_invert, separate_invert = false; 6325 GLenum format, type; 6326 GLint y1; 6327 uint32_t send_size = 0; 6328 uint32_t h = u_minify(res->base.height0, info->level); 6329 int elsize = util_format_get_blocksize(res->base.format); 6330 float depth_scale; 6331 int row_stride = info->stride / elsize; 6332 6333 vrend_use_program(ctx, 0); 6334 6335 format = tex_conv_table[res->base.format].glformat; 6336 type = tex_conv_table[res->base.format].gltype; 6337 /* if we are asked to invert and reading from a front then don't */ 6338 6339 actually_invert = res->y_0_top; 6340 6341 if (actually_invert && !has_feature(feat_mesa_invert)) 6342 separate_invert = true; 6343 6344 if (num_iovs > 1 || separate_invert) 6345 need_temp = 1; 6346 6347 if (need_temp) { 6348 send_size = util_format_get_nblocks(res->base.format, info->box->width, info->box->height) * info->box->depth * util_format_get_blocksize(res->base.format); 6349 data = malloc(send_size); 6350 if (!data) { 6351 fprintf(stderr,"malloc failed %d\n", send_size); 6352 return ENOMEM; 6353 } 6354 } else { 6355 send_size = iov[0].iov_len - info->offset; 6356 data = myptr; 6357 if (!row_stride) 6358 row_stride = util_format_get_nblocksx(res->base.format, u_minify(res->base.width0, info->level)); 6359 } 6360 6361 if (res->readback_fb_id == 0 || (int)res->readback_fb_level != info->level || 6362 (int)res->readback_fb_z != info->box->z) { 6363 6364 if (res->readback_fb_id) 6365 glDeleteFramebuffers(1, &res->readback_fb_id); 6366 6367 glGenFramebuffers(1, &fb_id); 6368 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_id); 6369 6370 vrend_fb_bind_texture(res, 0, info->level, info->box->z); 6371 6372 res->readback_fb_id = fb_id; 6373 res->readback_fb_level = info->level; 6374 res->readback_fb_z = info->box->z; 6375 } else 6376 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, res->readback_fb_id); 6377 if (actually_invert) 6378 y1 = h - info->box->y - info->box->height; 6379 else 6380 y1 = info->box->y; 6381 6382 if (has_feature(feat_mesa_invert) && actually_invert) 6383 glPixelStorei(GL_PACK_INVERT_MESA, 1); 6384 if (!vrend_format_is_ds(res->base.format)) 6385 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); 6386 if (!need_temp && row_stride) 6387 glPixelStorei(GL_PACK_ROW_LENGTH, row_stride); 6388 6389 switch (elsize) { 6390 case 1: 6391 glPixelStorei(GL_PACK_ALIGNMENT, 1); 6392 break; 6393 case 2: 6394 glPixelStorei(GL_PACK_ALIGNMENT, 2); 6395 break; 6396 case 4: 6397 default: 6398 glPixelStorei(GL_PACK_ALIGNMENT, 4); 6399 break; 6400 case 8: 6401 glPixelStorei(GL_PACK_ALIGNMENT, 8); 6402 break; 6403 } 6404 6405 if (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) { 6406 /* we get values from the guest as 24-bit scaled integers 6407 but we give them to the host GL and it interprets them 6408 as 32-bit scaled integers, so we need to scale them here */ 6409 depth_scale = 1.0 / 256.0; 6410 if (!vrend_state.use_core_profile) { 6411 glPixelTransferf(GL_DEPTH_SCALE, depth_scale); 6412 } 6413 } 6414 6415 /* Warn if the driver doesn't agree about the read format and type. 6416 On desktop GL we can use basically any format and type to glReadPixels, 6417 so we picked the format and type that matches the native format. 6418 6419 But on GLES we are limited to a very few set, luckily most GLES 6420 implementations should return type and format that match the native 6421 formats, and can be used for glReadPixels acording to the GLES spec. 6422 6423 But we have found that at least Mesa returned the wrong formats, again 6424 luckily we are able to change Mesa. But just in case there are more bad 6425 drivers out there, or we mess up the format somewhere, we warn here. */ 6426 if (vrend_state.use_gles) { 6427 GLint imp; 6428 if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_INT && 6429 type != GL_INT && type != GL_FLOAT) { 6430 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &imp); 6431 if (imp != (GLint)type) { 6432 fprintf(stderr, "GL_IMPLEMENTATION_COLOR_READ_TYPE is not expected native type 0x%x != imp 0x%x\n", type, imp); 6433 } 6434 } 6435 if (format != GL_RGBA && format != GL_RGBA_INTEGER) { 6436 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &imp); 6437 if (imp != (GLint)format) { 6438 fprintf(stderr, "GL_IMPLEMENTATION_COLOR_READ_FORMAT is not expected native format 0x%x != imp 0x%x\n", format, imp); 6439 } 6440 } 6441 } 6442 6443 if (has_feature(feat_arb_robustness)) 6444 glReadnPixelsARB(info->box->x, y1, info->box->width, info->box->height, format, type, send_size, data); 6445 else if (has_feature(feat_gles_khr_robustness)) 6446 glReadnPixelsKHR(info->box->x, y1, info->box->width, info->box->height, format, type, send_size, data); 6447 else 6448 glReadPixels(info->box->x, y1, info->box->width, info->box->height, format, type, data); 6449 6450 if (res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) { 6451 if (!vrend_state.use_core_profile) 6452 glPixelTransferf(GL_DEPTH_SCALE, 1.0); 6453 else 6454 vrend_scale_depth(data, send_size, depth_scale); 6455 } 6456 if (has_feature(feat_mesa_invert) && actually_invert) 6457 glPixelStorei(GL_PACK_INVERT_MESA, 0); 6458 if (!need_temp && row_stride) 6459 glPixelStorei(GL_PACK_ROW_LENGTH, 0); 6460 glPixelStorei(GL_PACK_ALIGNMENT, 4); 6461 if (need_temp) { 6462 write_transfer_data(&res->base, iov, num_iovs, data, 6463 info->stride, info->box, info->level, info->offset, 6464 separate_invert); 6465 free(data); 6466 } 6467 return 0; 6468 } 6469 6470 static int vrend_transfer_send_readonly(UNUSED struct vrend_context *ctx, 6471 struct vrend_resource *res, 6472 struct iovec *iov, int num_iovs, 6473 UNUSED const struct vrend_transfer_info *info) 6474 { 6475 bool same_iov = true; 6476 uint i; 6477 6478 if (res->num_iovs == (uint32_t)num_iovs) { 6479 for (i = 0; i < res->num_iovs; i++) { 6480 if (res->iov[i].iov_len != iov[i].iov_len || 6481 res->iov[i].iov_base != iov[i].iov_base) { 6482 same_iov = false; 6483 } 6484 } 6485 } else { 6486 same_iov = false; 6487 } 6488 6489 /* 6490 * When we detect that we are reading back to the same iovs that are 6491 * attached to the resource and we know that the resource can not 6492 * be rendered to (as this function is only called then), we do not 6493 * need to do anything more. 6494 */ 6495 if (same_iov) { 6496 return 0; 6497 } 6498 6499 /* Fallback to getteximage, will probably fail on GLES. */ 6500 return -1; 6501 } 6502 6503 static int vrend_renderer_transfer_send_iov(struct vrend_context *ctx, 6504 struct vrend_resource *res, 6505 struct iovec *iov, int num_iovs, 6506 const struct vrend_transfer_info *info) 6507 { 6508 if (res->target == 0 && res->ptr) { 6509 uint32_t send_size = info->box->width * util_format_get_blocksize(res->base.format); 6510 vrend_write_to_iovec(iov, num_iovs, info->offset, res->ptr + info->box->x, send_size); 6511 return 0; 6512 } 6513 6514 if (res->target == GL_ELEMENT_ARRAY_BUFFER_ARB || 6515 res->target == GL_ARRAY_BUFFER_ARB || 6516 res->target == GL_TRANSFORM_FEEDBACK_BUFFER || 6517 res->target == GL_TEXTURE_BUFFER || 6518 res->target == GL_UNIFORM_BUFFER) { 6519 uint32_t send_size = info->box->width * util_format_get_blocksize(res->base.format); 6520 void *data; 6521 6522 glBindBufferARB(res->target, res->id); 6523 data = glMapBufferRange(res->target, info->box->x, info->box->width, GL_MAP_READ_BIT); 6524 if (!data) 6525 fprintf(stderr,"unable to open buffer for reading %d\n", res->target); 6526 else 6527 vrend_write_to_iovec(iov, num_iovs, info->offset, data, send_size); 6528 glUnmapBuffer(res->target); 6529 } else { 6530 int ret = -1; 6531 bool can_readpixels = true; 6532 6533 can_readpixels = vrend_format_can_render(res->base.format) || vrend_format_is_ds(res->base.format); 6534 6535 if (can_readpixels) { 6536 ret = vrend_transfer_send_readpixels(ctx, res, iov, num_iovs, info); 6537 } else { 6538 ret = vrend_transfer_send_readonly(ctx, res, iov, num_iovs, info); 6539 } 6540 6541 /* Can hit this on a non-error path as well. */ 6542 if (ret != 0) { 6543 ret = vrend_transfer_send_getteximage(ctx, res, iov, num_iovs, info); 6544 } 6545 return ret; 6546 } 6547 return 0; 6548 } 6549 6550 int vrend_renderer_transfer_iov(const struct vrend_transfer_info *info, 6551 int transfer_mode) 6552 { 6553 struct vrend_resource *res; 6554 struct vrend_context *ctx; 6555 struct iovec *iov; 6556 int num_iovs; 6557 6558 if (!info->box) 6559 return EINVAL; 6560 6561 ctx = vrend_lookup_renderer_ctx(info->ctx_id); 6562 if (!ctx) 6563 return EINVAL; 6564 6565 if (info->ctx_id == 0) 6566 res = vrend_resource_lookup(info->handle, 0); 6567 else 6568 res = vrend_renderer_ctx_res_lookup(ctx, info->handle); 6569 6570 if (!res) { 6571 if (info->ctx_id) 6572 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, info->handle); 6573 return EINVAL; 6574 } 6575 6576 iov = info->iovec; 6577 num_iovs = info->iovec_cnt; 6578 6579 if (res->iov && (!iov || num_iovs == 0)) { 6580 iov = res->iov; 6581 num_iovs = res->num_iovs; 6582 } 6583 6584 if (!iov) { 6585 if (info->ctx_id) 6586 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, info->handle); 6587 return EINVAL; 6588 } 6589 6590 if (!check_transfer_bounds(res, info)) 6591 return EINVAL; 6592 6593 if (!check_iov_bounds(res, info, iov, num_iovs)) 6594 return EINVAL; 6595 6596 vrend_hw_switch_context(vrend_lookup_renderer_ctx(0), true); 6597 6598 if (transfer_mode == VREND_TRANSFER_WRITE) 6599 return vrend_renderer_transfer_write_iov(ctx, res, iov, num_iovs, 6600 info); 6601 else 6602 return vrend_renderer_transfer_send_iov(ctx, res, iov, num_iovs, 6603 info); 6604 } 6605 6606 int vrend_transfer_inline_write(struct vrend_context *ctx, 6607 struct vrend_transfer_info *info, 6608 UNUSED unsigned usage) 6609 { 6610 struct vrend_resource *res; 6611 6612 res = vrend_renderer_ctx_res_lookup(ctx, info->handle); 6613 if (!res) { 6614 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, info->handle); 6615 return EINVAL; 6616 } 6617 6618 if (!check_transfer_bounds(res, info)) { 6619 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, info->handle); 6620 return EINVAL; 6621 } 6622 6623 if (!check_iov_bounds(res, info, info->iovec, info->iovec_cnt)) { 6624 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, info->handle); 6625 return EINVAL; 6626 } 6627 6628 return vrend_renderer_transfer_write_iov(ctx, res, info->iovec, info->iovec_cnt, info); 6629 6630 } 6631 6632 void vrend_set_stencil_ref(struct vrend_context *ctx, 6633 struct pipe_stencil_ref *ref) 6634 { 6635 if (ctx->sub->stencil_refs[0] != ref->ref_value[0] || 6636 ctx->sub->stencil_refs[1] != ref->ref_value[1]) { 6637 ctx->sub->stencil_refs[0] = ref->ref_value[0]; 6638 ctx->sub->stencil_refs[1] = ref->ref_value[1]; 6639 ctx->sub->stencil_state_dirty = true; 6640 } 6641 } 6642 6643 void vrend_set_blend_color(struct vrend_context *ctx, 6644 struct pipe_blend_color *color) 6645 { 6646 ctx->sub->blend_color = *color; 6647 glBlendColor(color->color[0], color->color[1], color->color[2], 6648 color->color[3]); 6649 } 6650 6651 void vrend_set_scissor_state(struct vrend_context *ctx, 6652 uint32_t start_slot, 6653 uint32_t num_scissor, 6654 struct pipe_scissor_state *ss) 6655 { 6656 uint i, idx; 6657 6658 if (start_slot > PIPE_MAX_VIEWPORTS || 6659 num_scissor > (PIPE_MAX_VIEWPORTS - start_slot)) { 6660 vrend_report_buffer_error(ctx, 0); 6661 return; 6662 } 6663 6664 for (i = 0; i < num_scissor; i++) { 6665 idx = start_slot + i; 6666 ctx->sub->ss[idx] = ss[i]; 6667 ctx->sub->scissor_state_dirty |= (1 << idx); 6668 } 6669 } 6670 6671 void vrend_set_polygon_stipple(struct vrend_context *ctx, 6672 struct pipe_poly_stipple *ps) 6673 { 6674 if (vrend_state.use_core_profile) { 6675 static const unsigned bit31 = 1 << 31; 6676 GLubyte *stip = calloc(1, 1024); 6677 int i, j; 6678 6679 if (!ctx->pstip_inited) 6680 vrend_init_pstipple_texture(ctx); 6681 6682 if (!stip) 6683 return; 6684 6685 for (i = 0; i < 32; i++) { 6686 for (j = 0; j < 32; j++) { 6687 if (ps->stipple[i] & (bit31 >> j)) 6688 stip[i * 32 + j] = 0; 6689 else 6690 stip[i * 32 + j] = 255; 6691 } 6692 } 6693 6694 glBindTexture(GL_TEXTURE_2D, ctx->pstipple_tex_id); 6695 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 32, 32, 6696 GL_RED, GL_UNSIGNED_BYTE, stip); 6697 6698 free(stip); 6699 return; 6700 } 6701 glPolygonStipple((const GLubyte *)ps->stipple); 6702 } 6703 6704 void vrend_set_clip_state(struct vrend_context *ctx, struct pipe_clip_state *ucp) 6705 { 6706 if (vrend_state.use_core_profile) { 6707 ctx->sub->ucp_state = *ucp; 6708 } else { 6709 int i, j; 6710 GLdouble val[4]; 6711 6712 for (i = 0; i < 8; i++) { 6713 for (j = 0; j < 4; j++) 6714 val[j] = ucp->ucp[i][j]; 6715 glClipPlane(GL_CLIP_PLANE0 + i, val); 6716 } 6717 } 6718 } 6719 6720 void vrend_set_sample_mask(UNUSED struct vrend_context *ctx, unsigned sample_mask) 6721 { 6722 if (has_feature(feat_sample_mask)) 6723 glSampleMaski(0, sample_mask); 6724 } 6725 6726 void vrend_set_min_samples(struct vrend_context *ctx, unsigned min_samples) 6727 { 6728 float min_sample_shading = (float)min_samples; 6729 if (ctx->sub->nr_cbufs > 0 && ctx->sub->surf[0]) { 6730 assert(ctx->sub->surf[0]->texture); 6731 min_sample_shading /= MAX2(1, ctx->sub->surf[0]->texture->base.nr_samples); 6732 } 6733 6734 if (has_feature(feat_sample_shading)) 6735 glMinSampleShading(min_sample_shading); 6736 } 6737 6738 void vrend_set_tess_state(UNUSED struct vrend_context *ctx, const float tess_factors[6]) 6739 { 6740 if (has_feature(feat_tessellation)) { 6741 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, tess_factors); 6742 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, &tess_factors[4]); 6743 } 6744 } 6745 6746 static void vrend_hw_emit_streamout_targets(UNUSED struct vrend_context *ctx, struct vrend_streamout_object *so_obj) 6747 { 6748 uint i; 6749 6750 for (i = 0; i < so_obj->num_targets; i++) { 6751 if (so_obj->so_targets[i]->buffer_offset || so_obj->so_targets[i]->buffer_size < so_obj->so_targets[i]->buffer->base.width0) 6752 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, so_obj->so_targets[i]->buffer->id, so_obj->so_targets[i]->buffer_offset, so_obj->so_targets[i]->buffer_size); 6753 else 6754 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, so_obj->so_targets[i]->buffer->id); 6755 } 6756 } 6757 6758 void vrend_set_streamout_targets(struct vrend_context *ctx, 6759 UNUSED uint32_t append_bitmask, 6760 uint32_t num_targets, 6761 uint32_t *handles) 6762 { 6763 struct vrend_so_target *target; 6764 uint i; 6765 6766 if (!has_feature(feat_transform_feedback)) 6767 return; 6768 6769 if (num_targets) { 6770 bool found = false; 6771 struct vrend_streamout_object *obj; 6772 LIST_FOR_EACH_ENTRY(obj, &ctx->sub->streamout_list, head) { 6773 if (obj->num_targets == num_targets) { 6774 if (!memcmp(handles, obj->handles, num_targets * 4)) { 6775 found = true; 6776 break; 6777 } 6778 } 6779 } 6780 if (found) { 6781 ctx->sub->current_so = obj; 6782 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, obj->id); 6783 return; 6784 } 6785 6786 obj = CALLOC_STRUCT(vrend_streamout_object); 6787 if (has_feature(feat_transform_feedback2)) { 6788 glGenTransformFeedbacks(1, &obj->id); 6789 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, obj->id); 6790 } 6791 obj->num_targets = num_targets; 6792 for (i = 0; i < num_targets; i++) { 6793 obj->handles[i] = handles[i]; 6794 target = vrend_object_lookup(ctx->sub->object_hash, handles[i], VIRGL_OBJECT_STREAMOUT_TARGET); 6795 if (!target) { 6796 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handles[i]); 6797 free(obj); 6798 return; 6799 } 6800 vrend_so_target_reference(&obj->so_targets[i], target); 6801 } 6802 vrend_hw_emit_streamout_targets(ctx, obj); 6803 list_addtail(&obj->head, &ctx->sub->streamout_list); 6804 ctx->sub->current_so = obj; 6805 obj->xfb_state = XFB_STATE_STARTED_NEED_BEGIN; 6806 } else { 6807 if (has_feature(feat_transform_feedback2)) 6808 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); 6809 ctx->sub->current_so = NULL; 6810 } 6811 } 6812 6813 static void vrend_resource_buffer_copy(UNUSED struct vrend_context *ctx, 6814 struct vrend_resource *src_res, 6815 struct vrend_resource *dst_res, 6816 uint32_t dstx, uint32_t srcx, 6817 uint32_t width) 6818 { 6819 glBindBuffer(GL_COPY_READ_BUFFER, src_res->id); 6820 glBindBuffer(GL_COPY_WRITE_BUFFER, dst_res->id); 6821 6822 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcx, dstx, width); 6823 glBindBuffer(GL_COPY_READ_BUFFER, 0); 6824 glBindBuffer(GL_COPY_WRITE_BUFFER, 0); 6825 } 6826 6827 static void vrend_resource_copy_fallback(struct vrend_resource *src_res, 6828 struct vrend_resource *dst_res, 6829 uint32_t dst_level, 6830 uint32_t dstx, uint32_t dsty, 6831 uint32_t dstz, uint32_t src_level, 6832 const struct pipe_box *src_box) 6833 { 6834 char *tptr; 6835 uint32_t total_size, src_stride, dst_stride; 6836 GLenum glformat, gltype; 6837 int elsize = util_format_get_blocksize(dst_res->base.format); 6838 int compressed = util_format_is_compressed(dst_res->base.format); 6839 int cube_slice = 1; 6840 uint32_t slice_size, slice_offset; 6841 int i; 6842 struct pipe_box box; 6843 6844 if (src_res->target == GL_TEXTURE_CUBE_MAP) 6845 cube_slice = 6; 6846 6847 if (src_res->base.format != dst_res->base.format) { 6848 fprintf(stderr, "copy fallback failed due to mismatched formats %d %d\n", src_res->base.format, dst_res->base.format); 6849 return; 6850 } 6851 6852 box = *src_box; 6853 box.depth = vrend_get_texture_depth(src_res, src_level); 6854 dst_stride = util_format_get_stride(dst_res->base.format, dst_res->base.width0); 6855 6856 /* this is ugly need to do a full GetTexImage */ 6857 slice_size = util_format_get_nblocks(src_res->base.format, u_minify(src_res->base.width0, src_level), u_minify(src_res->base.height0, src_level)) * 6858 util_format_get_blocksize(src_res->base.format); 6859 total_size = slice_size * vrend_get_texture_depth(src_res, src_level); 6860 6861 tptr = malloc(total_size); 6862 if (!tptr) 6863 return; 6864 6865 glformat = tex_conv_table[src_res->base.format].glformat; 6866 gltype = tex_conv_table[src_res->base.format].gltype; 6867 6868 if (compressed) 6869 glformat = tex_conv_table[src_res->base.format].internalformat; 6870 6871 /* If we are on gles we need to rely on the textures backing 6872 * iovec to have the data we need, otherwise we can use glGetTexture 6873 */ 6874 if (vrend_state.use_gles) { 6875 uint64_t src_offset = 0; 6876 uint64_t dst_offset = 0; 6877 if (src_level < VR_MAX_TEXTURE_2D_LEVELS) { 6878 src_offset = src_res->mipmap_offsets[src_level]; 6879 dst_offset = dst_res->mipmap_offsets[src_level]; 6880 } 6881 6882 src_stride = util_format_get_nblocksx(src_res->base.format, 6883 u_minify(src_res->base.width0, src_level)) * elsize; 6884 read_transfer_data(&src_res->base, src_res->iov, src_res->num_iovs, tptr, 6885 src_stride, &box, src_level, src_offset, false); 6886 /* When on GLES sync the iov that backs the dst resource because 6887 * we might need it in a chain copy A->B, B->C */ 6888 write_transfer_data(&dst_res->base, dst_res->iov, dst_res->num_iovs, tptr, 6889 dst_stride, &box, src_level, dst_offset, false); 6890 /* we get values from the guest as 24-bit scaled integers 6891 but we give them to the host GL and it interprets them 6892 as 32-bit scaled integers, so we need to scale them here */ 6893 if (dst_res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) { 6894 float depth_scale = 256.0; 6895 vrend_scale_depth(tptr, total_size, depth_scale); 6896 } 6897 } else { 6898 uint32_t read_chunk_size; 6899 switch (elsize) { 6900 case 1: 6901 case 3: 6902 glPixelStorei(GL_PACK_ALIGNMENT, 1); 6903 break; 6904 case 2: 6905 case 6: 6906 glPixelStorei(GL_PACK_ALIGNMENT, 2); 6907 break; 6908 case 4: 6909 default: 6910 glPixelStorei(GL_PACK_ALIGNMENT, 4); 6911 break; 6912 case 8: 6913 glPixelStorei(GL_PACK_ALIGNMENT, 8); 6914 break; 6915 } 6916 glBindTexture(src_res->target, src_res->id); 6917 slice_offset = 0; 6918 read_chunk_size = (src_res->target == GL_TEXTURE_CUBE_MAP) ? slice_size : total_size; 6919 for (i = 0; i < cube_slice; i++) { 6920 GLenum ctarget = src_res->target == GL_TEXTURE_CUBE_MAP ? 6921 (GLenum)(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i) : src_res->target; 6922 if (compressed) { 6923 if (has_feature(feat_arb_robustness)) 6924 glGetnCompressedTexImageARB(ctarget, src_level, read_chunk_size, tptr + slice_offset); 6925 else 6926 glGetCompressedTexImage(ctarget, src_level, tptr + slice_offset); 6927 } else { 6928 if (has_feature(feat_arb_robustness)) 6929 glGetnTexImageARB(ctarget, src_level, glformat, gltype, read_chunk_size, tptr + slice_offset); 6930 else 6931 glGetTexImage(ctarget, src_level, glformat, gltype, tptr + slice_offset); 6932 } 6933 slice_offset += slice_size; 6934 } 6935 } 6936 6937 glPixelStorei(GL_PACK_ALIGNMENT, 4); 6938 switch (elsize) { 6939 case 1: 6940 case 3: 6941 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 6942 break; 6943 case 2: 6944 case 6: 6945 glPixelStorei(GL_UNPACK_ALIGNMENT, 2); 6946 break; 6947 case 4: 6948 default: 6949 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 6950 break; 6951 case 8: 6952 glPixelStorei(GL_UNPACK_ALIGNMENT, 8); 6953 break; 6954 } 6955 6956 glBindTexture(dst_res->target, dst_res->id); 6957 slice_offset = src_box->z * slice_size; 6958 cube_slice = (src_res->target == GL_TEXTURE_CUBE_MAP) ? src_box->z + src_box->depth : cube_slice; 6959 i = (src_res->target == GL_TEXTURE_CUBE_MAP) ? src_box->z : 0; 6960 for (; i < cube_slice; i++) { 6961 GLenum ctarget = dst_res->target == GL_TEXTURE_CUBE_MAP ? 6962 (GLenum)(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i) : dst_res->target; 6963 if (compressed) { 6964 if (ctarget == GL_TEXTURE_1D) { 6965 glCompressedTexSubImage1D(ctarget, dst_level, dstx, 6966 src_box->width, 6967 glformat, slice_size, tptr + slice_offset); 6968 } else { 6969 glCompressedTexSubImage2D(ctarget, dst_level, dstx, dsty, 6970 src_box->width, src_box->height, 6971 glformat, slice_size, tptr + slice_offset); 6972 } 6973 } else { 6974 if (ctarget == GL_TEXTURE_1D) { 6975 glTexSubImage1D(ctarget, dst_level, dstx, src_box->width, glformat, gltype, tptr + slice_offset); 6976 } else if (ctarget == GL_TEXTURE_3D || 6977 ctarget == GL_TEXTURE_2D_ARRAY || 6978 ctarget == GL_TEXTURE_CUBE_MAP_ARRAY) { 6979 glTexSubImage3D(ctarget, dst_level, dstx, dsty, dstz, src_box->width, src_box->height, src_box->depth, glformat, gltype, tptr + slice_offset); 6980 } else { 6981 glTexSubImage2D(ctarget, dst_level, dstx, dsty, src_box->width, src_box->height, glformat, gltype, tptr + slice_offset); 6982 } 6983 } 6984 slice_offset += slice_size; 6985 } 6986 6987 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 6988 free(tptr); 6989 } 6990 6991 6992 static inline void 6993 vrend_copy_sub_image(struct vrend_resource* src_res, struct vrend_resource * dst_res, 6994 uint32_t src_level, const struct pipe_box *src_box, 6995 uint32_t dst_level, uint32_t dstx, uint32_t dsty, uint32_t dstz) 6996 { 6997 glCopyImageSubData(src_res->id, 6998 tgsitargettogltarget(src_res->base.target, src_res->base.nr_samples), 6999 src_level, src_box->x, src_box->y, src_box->z, 7000 dst_res->id, 7001 tgsitargettogltarget(dst_res->base.target, dst_res->base.nr_samples), 7002 dst_level, dstx, dsty, dstz, 7003 src_box->width, src_box->height,src_box->depth); 7004 } 7005 7006 7007 void vrend_renderer_resource_copy_region(struct vrend_context *ctx, 7008 uint32_t dst_handle, uint32_t dst_level, 7009 uint32_t dstx, uint32_t dsty, uint32_t dstz, 7010 uint32_t src_handle, uint32_t src_level, 7011 const struct pipe_box *src_box) 7012 { 7013 struct vrend_resource *src_res, *dst_res; 7014 GLbitfield glmask = 0; 7015 GLint sy1, sy2, dy1, dy2; 7016 7017 if (ctx->in_error) 7018 return; 7019 7020 src_res = vrend_renderer_ctx_res_lookup(ctx, src_handle); 7021 dst_res = vrend_renderer_ctx_res_lookup(ctx, dst_handle); 7022 7023 if (!src_res) { 7024 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, src_handle); 7025 return; 7026 } 7027 if (!dst_res) { 7028 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle); 7029 return; 7030 } 7031 7032 if (src_res->base.target == PIPE_BUFFER && dst_res->base.target == PIPE_BUFFER) { 7033 /* do a buffer copy */ 7034 vrend_resource_buffer_copy(ctx, src_res, dst_res, dstx, 7035 src_box->x, src_box->width); 7036 return; 7037 } 7038 7039 if (has_feature(feat_copy_image) && 7040 format_is_copy_compatible(src_res->base.format,dst_res->base.format, true) && 7041 src_res->base.nr_samples == dst_res->base.nr_samples) { 7042 vrend_copy_sub_image(src_res, dst_res, src_level, src_box, 7043 dst_level, dstx, dsty, dstz); 7044 return; 7045 } 7046 7047 if (!vrend_format_can_render(src_res->base.format) || 7048 !vrend_format_can_render(dst_res->base.format)) { 7049 vrend_resource_copy_fallback(src_res, dst_res, dst_level, dstx, 7050 dsty, dstz, src_level, src_box); 7051 return; 7052 } 7053 7054 glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->sub->blit_fb_ids[0]); 7055 /* clean out fb ids */ 7056 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, 7057 GL_TEXTURE_2D, 0, 0); 7058 vrend_fb_bind_texture(src_res, 0, src_level, src_box->z); 7059 7060 glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->sub->blit_fb_ids[1]); 7061 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, 7062 GL_TEXTURE_2D, 0, 0); 7063 vrend_fb_bind_texture(dst_res, 0, dst_level, dstz); 7064 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ctx->sub->blit_fb_ids[1]); 7065 7066 glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->sub->blit_fb_ids[0]); 7067 7068 glmask = GL_COLOR_BUFFER_BIT; 7069 glDisable(GL_SCISSOR_TEST); 7070 7071 if (!src_res->y_0_top) { 7072 sy1 = src_box->y; 7073 sy2 = src_box->y + src_box->height; 7074 } else { 7075 sy1 = src_res->base.height0 - src_box->y - src_box->height; 7076 sy2 = src_res->base.height0 - src_box->y; 7077 } 7078 7079 if (!dst_res->y_0_top) { 7080 dy1 = dsty; 7081 dy2 = dsty + src_box->height; 7082 } else { 7083 dy1 = dst_res->base.height0 - dsty - src_box->height; 7084 dy2 = dst_res->base.height0 - dsty; 7085 } 7086 7087 glBlitFramebuffer(src_box->x, sy1, 7088 src_box->x + src_box->width, 7089 sy2, 7090 dstx, dy1, 7091 dstx + src_box->width, 7092 dy2, 7093 glmask, GL_NEAREST); 7094 7095 } 7096 7097 static void vrend_renderer_blit_int(struct vrend_context *ctx, 7098 struct vrend_resource *src_res, 7099 struct vrend_resource *dst_res, 7100 const struct pipe_blit_info *info) 7101 { 7102 GLbitfield glmask = 0; 7103 int src_y1, src_y2, dst_y1, dst_y2; 7104 GLenum filter; 7105 int n_layers = 1, i; 7106 bool use_gl = false; 7107 bool make_intermediate_copy = false; 7108 GLuint intermediate_fbo = 0; 7109 struct vrend_resource *intermediate_copy = 0; 7110 7111 filter = convert_mag_filter(info->filter); 7112 7113 /* if we can't make FBO's use the fallback path */ 7114 if (!vrend_format_can_render(src_res->base.format) && 7115 !vrend_format_is_ds(src_res->base.format)) 7116 use_gl = true; 7117 if (!vrend_format_can_render(dst_res->base.format) && 7118 !vrend_format_is_ds(dst_res->base.format)) 7119 use_gl = true; 7120 7121 if (util_format_is_srgb(src_res->base.format) && 7122 !util_format_is_srgb(dst_res->base.format)) 7123 use_gl = true; 7124 7125 /* different depth formats */ 7126 if (vrend_format_is_ds(src_res->base.format) && 7127 vrend_format_is_ds(dst_res->base.format)) { 7128 if (src_res->base.format != dst_res->base.format) { 7129 if (!(src_res->base.format == PIPE_FORMAT_S8_UINT_Z24_UNORM && 7130 (dst_res->base.format == PIPE_FORMAT_Z24X8_UNORM))) { 7131 use_gl = true; 7132 } 7133 } 7134 } 7135 /* glBlitFramebuffer - can support depth stencil with NEAREST 7136 which we use for mipmaps */ 7137 if ((info->mask & (PIPE_MASK_Z | PIPE_MASK_S)) && info->filter == PIPE_TEX_FILTER_LINEAR) 7138 use_gl = true; 7139 7140 /* for scaled MS blits we either need extensions or hand roll */ 7141 if (info->mask & PIPE_MASK_RGBA && 7142 src_res->base.nr_samples > 1 && 7143 src_res->base.nr_samples != dst_res->base.nr_samples && 7144 (info->src.box.width != info->dst.box.width || 7145 info->src.box.height != info->dst.box.height)) { 7146 if (has_feature(feat_ms_scaled_blit)) 7147 filter = GL_SCALED_RESOLVE_NICEST_EXT; 7148 else 7149 use_gl = true; 7150 } 7151 7152 /* for 3D mipmapped blits - hand roll time */ 7153 if (info->src.box.depth != info->dst.box.depth) 7154 use_gl = true; 7155 7156 if (vrend_format_needs_swizzle(info->dst.format) || 7157 vrend_format_needs_swizzle(info->src.format)) 7158 use_gl = true; 7159 7160 if (use_gl) { 7161 vrend_renderer_blit_gl(ctx, src_res, dst_res, info, 7162 has_feature(feat_texture_srgb_decode)); 7163 vrend_clicbs->make_current(0, ctx->sub->gl_context); 7164 return; 7165 } 7166 7167 if (info->mask & PIPE_MASK_Z) 7168 glmask |= GL_DEPTH_BUFFER_BIT; 7169 if (info->mask & PIPE_MASK_S) 7170 glmask |= GL_STENCIL_BUFFER_BIT; 7171 if (info->mask & PIPE_MASK_RGBA) 7172 glmask |= GL_COLOR_BUFFER_BIT; 7173 7174 if (!dst_res->y_0_top) { 7175 dst_y1 = info->dst.box.y + info->dst.box.height; 7176 dst_y2 = info->dst.box.y; 7177 } else { 7178 dst_y1 = dst_res->base.height0 - info->dst.box.y - info->dst.box.height; 7179 dst_y2 = dst_res->base.height0 - info->dst.box.y; 7180 } 7181 7182 if (!src_res->y_0_top) { 7183 src_y1 = info->src.box.y + info->src.box.height; 7184 src_y2 = info->src.box.y; 7185 } else { 7186 src_y1 = src_res->base.height0 - info->src.box.y - info->src.box.height; 7187 src_y2 = src_res->base.height0 - info->src.box.y; 7188 } 7189 7190 if (info->scissor_enable) { 7191 glScissor(info->scissor.minx, info->scissor.miny, info->scissor.maxx - info->scissor.minx, info->scissor.maxy - info->scissor.miny); 7192 glEnable(GL_SCISSOR_TEST); 7193 } else 7194 glDisable(GL_SCISSOR_TEST); 7195 ctx->sub->scissor_state_dirty = (1 << 0); 7196 7197 /* An GLES GL_INVALID_OPERATION is generated if one wants to blit from a 7198 * multi-sample fbo to a non multi-sample fbo and the source and destination 7199 * rectangles are not defined with the same (X0, Y0) and (X1, Y1) bounds. 7200 * 7201 * Since stencil data can only be written in a fragment shader when 7202 * ARB_shader_stencil_export is available, the workaround using GL as given 7203 * above is usually not available. Instead, to work around the blit 7204 * limitations on GLES first copy the full frame to a non-multisample 7205 * surface and then copy the according area to the final target surface. 7206 */ 7207 if (vrend_state.use_gles && 7208 (info->mask & PIPE_MASK_ZS) && 7209 ((src_res->base.nr_samples > 1) && 7210 (src_res->base.nr_samples != dst_res->base.nr_samples)) && 7211 ((info->src.box.x != info->dst.box.x) || 7212 (src_y1 != dst_y1) || 7213 (info->src.box.width != info->dst.box.width) || 7214 (src_y2 != dst_y2))) { 7215 7216 make_intermediate_copy = true; 7217 7218 /* Create a texture that is the same like the src_res texture, but 7219 * without multi-sample */ 7220 struct vrend_renderer_resource_create_args args; 7221 memset(&args, 0, sizeof(struct vrend_renderer_resource_create_args)); 7222 args.width = src_res->base.width0; 7223 args.height = src_res->base.height0; 7224 args.depth = src_res->base.depth0; 7225 args.format = src_res->base.format; 7226 args.target = src_res->base.target; 7227 args.last_level = src_res->base.last_level; 7228 args.array_size = src_res->base.array_size; 7229 intermediate_copy = (struct vrend_resource *)CALLOC_STRUCT(vrend_texture); 7230 vrend_renderer_resource_copy_args(&args, intermediate_copy); 7231 vrend_renderer_resource_allocate_texture(intermediate_copy, NULL); 7232 7233 glGenFramebuffers(1, &intermediate_fbo); 7234 } else { 7235 /* If no intermediate copy is needed make the variables point to the 7236 * original source to simplify the code below. 7237 */ 7238 intermediate_fbo = ctx->sub->blit_fb_ids[0]; 7239 intermediate_copy = src_res; 7240 } 7241 7242 glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->sub->blit_fb_ids[0]); 7243 if (info->mask & PIPE_MASK_RGBA) 7244 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, 7245 GL_TEXTURE_2D, 0, 0); 7246 else 7247 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, 7248 GL_TEXTURE_2D, 0, 0); 7249 glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->sub->blit_fb_ids[1]); 7250 if (info->mask & PIPE_MASK_RGBA) 7251 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, 7252 GL_TEXTURE_2D, 0, 0); 7253 else if (info->mask & (PIPE_MASK_Z | PIPE_MASK_S)) 7254 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, 7255 GL_TEXTURE_2D, 0, 0); 7256 if (info->src.box.depth == info->dst.box.depth) 7257 n_layers = info->dst.box.depth; 7258 for (i = 0; i < n_layers; i++) { 7259 glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->sub->blit_fb_ids[0]); 7260 vrend_fb_bind_texture(src_res, 0, info->src.level, info->src.box.z + i); 7261 7262 if (make_intermediate_copy) { 7263 int level_width = u_minify(src_res->base.width0, info->src.level); 7264 int level_height = u_minify(src_res->base.width0, info->src.level); 7265 glBindFramebuffer(GL_FRAMEBUFFER_EXT, intermediate_fbo); 7266 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, 7267 GL_TEXTURE_2D, 0, 0); 7268 vrend_fb_bind_texture(intermediate_copy, 0, info->src.level, info->src.box.z + i); 7269 7270 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediate_fbo); 7271 glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->sub->blit_fb_ids[0]); 7272 glBlitFramebuffer(0, 0, level_width, level_height, 7273 0, 0, level_width, level_height, 7274 glmask, filter); 7275 } 7276 7277 glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->sub->blit_fb_ids[1]); 7278 vrend_fb_bind_texture(dst_res, 0, info->dst.level, info->dst.box.z + i); 7279 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ctx->sub->blit_fb_ids[1]); 7280 7281 if (!vrend_state.use_gles) { 7282 if (util_format_is_srgb(dst_res->base.format)) 7283 glEnable(GL_FRAMEBUFFER_SRGB); 7284 else 7285 glDisable(GL_FRAMEBUFFER_SRGB); 7286 } 7287 7288 glBindFramebuffer(GL_READ_FRAMEBUFFER, intermediate_fbo); 7289 7290 glBlitFramebuffer(info->src.box.x, 7291 src_y1, 7292 info->src.box.x + info->src.box.width, 7293 src_y2, 7294 info->dst.box.x, 7295 dst_y1, 7296 info->dst.box.x + info->dst.box.width, 7297 dst_y2, 7298 glmask, filter); 7299 } 7300 7301 if (make_intermediate_copy) { 7302 vrend_renderer_resource_destroy(intermediate_copy, false); 7303 glDeleteFramebuffers(1, &intermediate_fbo); 7304 } 7305 } 7306 7307 void vrend_renderer_blit(struct vrend_context *ctx, 7308 uint32_t dst_handle, uint32_t src_handle, 7309 const struct pipe_blit_info *info) 7310 { 7311 struct vrend_resource *src_res, *dst_res; 7312 src_res = vrend_renderer_ctx_res_lookup(ctx, src_handle); 7313 dst_res = vrend_renderer_ctx_res_lookup(ctx, dst_handle); 7314 7315 if (!src_res) { 7316 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, src_handle); 7317 return; 7318 } 7319 if (!dst_res) { 7320 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle); 7321 return; 7322 } 7323 7324 if (ctx->in_error) 7325 return; 7326 7327 if (info->render_condition_enable == false) 7328 vrend_pause_render_condition(ctx, true); 7329 7330 /* The Gallium blit function can be called for a general blit that may 7331 * scale, convert the data, and apply some rander states, or it is called via 7332 * glCopyImageSubData. If the src or the dst image are equal, or the two 7333 * images formats are the same, then Galliums such calles are redirected 7334 * to resource_copy_region, in this case and if no render states etx need 7335 * to be applied, forward the call to glCopyImageSubData, otherwise do a 7336 * normal blit. */ 7337 if (has_feature(feat_copy_image) && !info->render_condition_enable && 7338 (src_res->base.format != dst_res->base.format) && 7339 format_is_copy_compatible(info->src.format,info->dst.format, false) && 7340 !info->scissor_enable && (info->filter == PIPE_TEX_FILTER_NEAREST) && 7341 !info->alpha_blend && (info->mask == PIPE_MASK_RGBA) && 7342 (src_res->base.nr_samples == dst_res->base.nr_samples) && 7343 info->src.box.width == info->dst.box.width && 7344 info->src.box.height == info->dst.box.height && 7345 info->src.box.depth == info->dst.box.depth) { 7346 vrend_copy_sub_image(src_res, dst_res, info->src.level, &info->src.box, 7347 info->dst.level, info->dst.box.x, info->dst.box.y, 7348 info->dst.box.z); 7349 } else { 7350 vrend_renderer_blit_int(ctx, src_res, dst_res, info); 7351 } 7352 7353 if (info->render_condition_enable == false) 7354 vrend_pause_render_condition(ctx, false); 7355 } 7356 7357 int vrend_renderer_create_fence(int client_fence_id, uint32_t ctx_id) 7358 { 7359 struct vrend_fence *fence; 7360 7361 fence = malloc(sizeof(struct vrend_fence)); 7362 if (!fence) 7363 return ENOMEM; 7364 7365 fence->ctx_id = ctx_id; 7366 fence->fence_id = client_fence_id; 7367 fence->syncobj = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 7368 glFlush(); 7369 7370 if (fence->syncobj == NULL) 7371 goto fail; 7372 7373 if (vrend_state.sync_thread) { 7374 pipe_mutex_lock(vrend_state.fence_mutex); 7375 list_addtail(&fence->fences, &vrend_state.fence_wait_list); 7376 pipe_condvar_signal(vrend_state.fence_cond); 7377 pipe_mutex_unlock(vrend_state.fence_mutex); 7378 } else 7379 list_addtail(&fence->fences, &vrend_state.fence_list); 7380 return 0; 7381 7382 fail: 7383 fprintf(stderr, "failed to create fence sync object\n"); 7384 free(fence); 7385 return ENOMEM; 7386 } 7387 7388 static void free_fence_locked(struct vrend_fence *fence) 7389 { 7390 list_del(&fence->fences); 7391 glDeleteSync(fence->syncobj); 7392 free(fence); 7393 } 7394 7395 static void flush_eventfd(int fd) 7396 { 7397 ssize_t len; 7398 uint64_t value; 7399 do { 7400 len = read(fd, &value, sizeof(value)); 7401 } while ((len == -1 && errno == EINTR) || len == sizeof(value)); 7402 } 7403 7404 void vrend_renderer_check_fences(void) 7405 { 7406 struct vrend_fence *fence, *stor; 7407 uint32_t latest_id = 0; 7408 GLenum glret; 7409 7410 if (!vrend_state.inited) 7411 return; 7412 7413 if (vrend_state.sync_thread) { 7414 flush_eventfd(vrend_state.eventfd); 7415 pipe_mutex_lock(vrend_state.fence_mutex); 7416 LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) { 7417 if (fence->fence_id > latest_id) 7418 latest_id = fence->fence_id; 7419 free_fence_locked(fence); 7420 } 7421 pipe_mutex_unlock(vrend_state.fence_mutex); 7422 } else { 7423 vrend_renderer_force_ctx_0(); 7424 7425 LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) { 7426 glret = glClientWaitSync(fence->syncobj, 0, 0); 7427 if (glret == GL_ALREADY_SIGNALED){ 7428 latest_id = fence->fence_id; 7429 free_fence_locked(fence); 7430 } 7431 /* don't bother checking any subsequent ones */ 7432 else if (glret == GL_TIMEOUT_EXPIRED) { 7433 break; 7434 } 7435 } 7436 } 7437 7438 if (latest_id == 0) 7439 return; 7440 vrend_clicbs->write_fence(latest_id); 7441 } 7442 7443 static bool vrend_get_one_query_result(GLuint query_id, bool use_64, uint64_t *result) 7444 { 7445 GLuint ready; 7446 GLuint passed; 7447 GLuint64 pass64; 7448 7449 glGetQueryObjectuiv(query_id, GL_QUERY_RESULT_AVAILABLE_ARB, &ready); 7450 7451 if (!ready) 7452 return false; 7453 7454 if (use_64) { 7455 glGetQueryObjectui64v(query_id, GL_QUERY_RESULT_ARB, &pass64); 7456 *result = pass64; 7457 } else { 7458 glGetQueryObjectuiv(query_id, GL_QUERY_RESULT_ARB, &passed); 7459 *result = passed; 7460 } 7461 return true; 7462 } 7463 7464 static bool vrend_check_query(struct vrend_query *query) 7465 { 7466 uint64_t result; 7467 struct virgl_host_query_state *state; 7468 bool ret; 7469 7470 ret = vrend_get_one_query_result(query->id, vrend_is_timer_query(query->gltype), &result); 7471 if (ret == false) 7472 return false; 7473 7474 state = (struct virgl_host_query_state *)query->res->ptr; 7475 state->result = result; 7476 state->query_state = VIRGL_QUERY_STATE_DONE; 7477 return true; 7478 } 7479 7480 void vrend_renderer_check_queries(void) 7481 { 7482 struct vrend_query *query, *stor; 7483 7484 if (!vrend_state.inited) 7485 return; 7486 7487 LIST_FOR_EACH_ENTRY_SAFE(query, stor, &vrend_state.waiting_query_list, waiting_queries) { 7488 vrend_hw_switch_context(vrend_lookup_renderer_ctx(query->ctx_id), true); 7489 if (vrend_check_query(query)) 7490 list_delinit(&query->waiting_queries); 7491 } 7492 } 7493 7494 bool vrend_hw_switch_context(struct vrend_context *ctx, bool now) 7495 { 7496 if (ctx == vrend_state.current_ctx && ctx->ctx_switch_pending == false) 7497 return true; 7498 7499 if (ctx->ctx_id != 0 && ctx->in_error) { 7500 return false; 7501 } 7502 7503 ctx->ctx_switch_pending = true; 7504 if (now == true) { 7505 vrend_finish_context_switch(ctx); 7506 } 7507 vrend_state.current_ctx = ctx; 7508 return true; 7509 } 7510 7511 static void vrend_finish_context_switch(struct vrend_context *ctx) 7512 { 7513 if (ctx->ctx_switch_pending == false) 7514 return; 7515 ctx->ctx_switch_pending = false; 7516 7517 if (vrend_state.current_hw_ctx == ctx) 7518 return; 7519 7520 vrend_state.current_hw_ctx = ctx; 7521 7522 vrend_clicbs->make_current(0, ctx->sub->gl_context); 7523 } 7524 7525 void 7526 vrend_renderer_object_destroy(struct vrend_context *ctx, uint32_t handle) 7527 { 7528 vrend_object_remove(ctx->sub->object_hash, handle, 0); 7529 } 7530 7531 uint32_t vrend_renderer_object_insert(struct vrend_context *ctx, void *data, 7532 uint32_t size, uint32_t handle, enum virgl_object_type type) 7533 { 7534 return vrend_object_insert(ctx->sub->object_hash, data, size, handle, type); 7535 } 7536 7537 int vrend_create_query(struct vrend_context *ctx, uint32_t handle, 7538 uint32_t query_type, uint32_t query_index, 7539 uint32_t res_handle, UNUSED uint32_t offset) 7540 { 7541 struct vrend_query *q; 7542 struct vrend_resource *res; 7543 uint32_t ret_handle; 7544 res = vrend_renderer_ctx_res_lookup(ctx, res_handle); 7545 if (!res) { 7546 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); 7547 return EINVAL; 7548 } 7549 7550 q = CALLOC_STRUCT(vrend_query); 7551 if (!q) 7552 return ENOMEM; 7553 7554 list_inithead(&q->waiting_queries); 7555 q->type = query_type; 7556 q->index = query_index; 7557 q->ctx_id = ctx->ctx_id; 7558 7559 vrend_resource_reference(&q->res, res); 7560 7561 switch (q->type) { 7562 case PIPE_QUERY_OCCLUSION_COUNTER: 7563 q->gltype = GL_SAMPLES_PASSED_ARB; 7564 break; 7565 case PIPE_QUERY_OCCLUSION_PREDICATE: 7566 q->gltype = GL_ANY_SAMPLES_PASSED; 7567 break; 7568 case PIPE_QUERY_TIMESTAMP: 7569 q->gltype = GL_TIMESTAMP; 7570 break; 7571 case PIPE_QUERY_TIME_ELAPSED: 7572 q->gltype = GL_TIME_ELAPSED; 7573 break; 7574 case PIPE_QUERY_PRIMITIVES_GENERATED: 7575 q->gltype = GL_PRIMITIVES_GENERATED; 7576 break; 7577 case PIPE_QUERY_PRIMITIVES_EMITTED: 7578 q->gltype = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN; 7579 break; 7580 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 7581 q->gltype = GL_ANY_SAMPLES_PASSED_CONSERVATIVE; 7582 break; 7583 case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 7584 if (!has_feature(feat_transform_feedback_overflow_query)) 7585 return EINVAL; 7586 q->gltype = GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB; 7587 break; 7588 case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 7589 if (!has_feature(feat_transform_feedback_overflow_query)) 7590 return EINVAL; 7591 q->gltype = GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB; 7592 break; 7593 default: 7594 fprintf(stderr,"unknown query object received %d\n", q->type); 7595 break; 7596 } 7597 7598 glGenQueries(1, &q->id); 7599 7600 ret_handle = vrend_renderer_object_insert(ctx, q, sizeof(struct vrend_query), handle, 7601 VIRGL_OBJECT_QUERY); 7602 if (!ret_handle) { 7603 FREE(q); 7604 return ENOMEM; 7605 } 7606 return 0; 7607 } 7608 7609 static void vrend_destroy_query(struct vrend_query *query) 7610 { 7611 vrend_resource_reference(&query->res, NULL); 7612 list_del(&query->waiting_queries); 7613 glDeleteQueries(1, &query->id); 7614 free(query); 7615 } 7616 7617 static void vrend_destroy_query_object(void *obj_ptr) 7618 { 7619 struct vrend_query *query = obj_ptr; 7620 vrend_destroy_query(query); 7621 } 7622 7623 int vrend_begin_query(struct vrend_context *ctx, uint32_t handle) 7624 { 7625 struct vrend_query *q; 7626 7627 q = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_QUERY); 7628 if (!q) 7629 return EINVAL; 7630 7631 if (q->index > 0 && !has_feature(feat_transform_feedback3)) 7632 return EINVAL; 7633 7634 if (q->gltype == GL_TIMESTAMP) 7635 return 0; 7636 7637 if (q->index > 0) 7638 glBeginQueryIndexed(q->gltype, q->index, q->id); 7639 else 7640 glBeginQuery(q->gltype, q->id); 7641 return 0; 7642 } 7643 7644 int vrend_end_query(struct vrend_context *ctx, uint32_t handle) 7645 { 7646 struct vrend_query *q; 7647 q = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_QUERY); 7648 if (!q) 7649 return EINVAL; 7650 7651 if (q->index > 0 && !has_feature(feat_transform_feedback3)) 7652 return EINVAL; 7653 7654 if (vrend_is_timer_query(q->gltype)) { 7655 if (vrend_state.use_gles && q->gltype == GL_TIMESTAMP) { 7656 report_gles_warn(ctx, GLES_WARN_TIMESTAMP, 0); 7657 } else if (q->gltype == GL_TIMESTAMP) { 7658 glQueryCounter(q->id, q->gltype); 7659 } else { 7660 /* remove from active query list for this context */ 7661 glEndQuery(q->gltype); 7662 } 7663 return 0; 7664 } 7665 7666 if (q->index > 0) 7667 glEndQueryIndexed(q->gltype, q->index); 7668 else 7669 glEndQuery(q->gltype); 7670 return 0; 7671 } 7672 7673 void vrend_get_query_result(struct vrend_context *ctx, uint32_t handle, 7674 UNUSED uint32_t wait) 7675 { 7676 struct vrend_query *q; 7677 bool ret; 7678 7679 q = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_QUERY); 7680 if (!q) 7681 return; 7682 7683 ret = vrend_check_query(q); 7684 if (ret == false) 7685 list_addtail(&q->waiting_queries, &vrend_state.waiting_query_list); 7686 } 7687 7688 static void vrend_pause_render_condition(struct vrend_context *ctx, bool pause) 7689 { 7690 if (pause) { 7691 if (ctx->sub->cond_render_q_id) { 7692 if (has_feature(feat_gl_conditional_render)) 7693 glEndConditionalRender(); 7694 else if (has_feature(feat_nv_conditional_render)) 7695 glEndConditionalRenderNV(); 7696 } 7697 } else { 7698 if (ctx->sub->cond_render_q_id) { 7699 if (has_feature(feat_gl_conditional_render)) 7700 glBeginConditionalRender(ctx->sub->cond_render_q_id, 7701 ctx->sub->cond_render_gl_mode); 7702 else if (has_feature(feat_nv_conditional_render)) 7703 glBeginConditionalRenderNV(ctx->sub->cond_render_q_id, 7704 ctx->sub->cond_render_gl_mode); 7705 } 7706 } 7707 } 7708 7709 void vrend_render_condition(struct vrend_context *ctx, 7710 uint32_t handle, 7711 bool condition, 7712 uint mode) 7713 { 7714 struct vrend_query *q; 7715 GLenum glmode = 0; 7716 7717 if (handle == 0) { 7718 if (has_feature(feat_gl_conditional_render)) 7719 glEndConditionalRender(); 7720 else if (has_feature(feat_nv_conditional_render)) 7721 glEndConditionalRenderNV(); 7722 ctx->sub->cond_render_q_id = 0; 7723 ctx->sub->cond_render_gl_mode = 0; 7724 return; 7725 } 7726 7727 q = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_QUERY); 7728 if (!q) 7729 return; 7730 7731 if (condition && !has_feature(feat_conditional_render_inverted)) 7732 return; 7733 switch (mode) { 7734 case PIPE_RENDER_COND_WAIT: 7735 glmode = condition ? GL_QUERY_WAIT_INVERTED : GL_QUERY_WAIT; 7736 break; 7737 case PIPE_RENDER_COND_NO_WAIT: 7738 glmode = condition ? GL_QUERY_NO_WAIT_INVERTED : GL_QUERY_NO_WAIT; 7739 break; 7740 case PIPE_RENDER_COND_BY_REGION_WAIT: 7741 glmode = condition ? GL_QUERY_BY_REGION_WAIT_INVERTED : GL_QUERY_BY_REGION_WAIT; 7742 break; 7743 case PIPE_RENDER_COND_BY_REGION_NO_WAIT: 7744 glmode = condition ? GL_QUERY_BY_REGION_NO_WAIT_INVERTED : GL_QUERY_BY_REGION_NO_WAIT; 7745 break; 7746 default: 7747 fprintf(stderr, "unhandled condition %x\n", mode); 7748 } 7749 7750 ctx->sub->cond_render_q_id = q->id; 7751 ctx->sub->cond_render_gl_mode = glmode; 7752 if (has_feature(feat_gl_conditional_render)) 7753 glBeginConditionalRender(q->id, glmode); 7754 if (has_feature(feat_nv_conditional_render)) 7755 glBeginConditionalRenderNV(q->id, glmode); 7756 } 7757 7758 int vrend_create_so_target(struct vrend_context *ctx, 7759 uint32_t handle, 7760 uint32_t res_handle, 7761 uint32_t buffer_offset, 7762 uint32_t buffer_size) 7763 { 7764 struct vrend_so_target *target; 7765 struct vrend_resource *res; 7766 int ret_handle; 7767 res = vrend_renderer_ctx_res_lookup(ctx, res_handle); 7768 if (!res) { 7769 report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle); 7770 return EINVAL; 7771 } 7772 7773 target = CALLOC_STRUCT(vrend_so_target); 7774 if (!target) 7775 return ENOMEM; 7776 7777 pipe_reference_init(&target->reference, 1); 7778 target->res_handle = res_handle; 7779 target->buffer_offset = buffer_offset; 7780 target->buffer_size = buffer_size; 7781 target->sub_ctx = ctx->sub; 7782 vrend_resource_reference(&target->buffer, res); 7783 7784 ret_handle = vrend_renderer_object_insert(ctx, target, sizeof(*target), handle, 7785 VIRGL_OBJECT_STREAMOUT_TARGET); 7786 if (ret_handle == 0) { 7787 FREE(target); 7788 return ENOMEM; 7789 } 7790 return 0; 7791 } 7792 7793 static void vrender_get_glsl_version(int *glsl_version) 7794 { 7795 int major_local, minor_local; 7796 const GLubyte *version_str; 7797 int c; 7798 int version; 7799 7800 version_str = glGetString(GL_SHADING_LANGUAGE_VERSION); 7801 if (vrend_state.use_gles) { 7802 char tmp[20]; 7803 c = sscanf((const char *)version_str, "%s %s %s %s %i.%i", 7804 tmp, tmp, tmp, tmp, &major_local, &minor_local); 7805 assert(c == 6); 7806 } else { 7807 c = sscanf((const char *)version_str, "%i.%i", 7808 &major_local, &minor_local); 7809 assert(c == 2); 7810 } 7811 7812 version = (major_local * 100) + minor_local; 7813 if (glsl_version) 7814 *glsl_version = version; 7815 } 7816 7817 static void vrend_fill_caps_glsl_version(int gl_ver, int gles_ver, 7818 union virgl_caps *caps) 7819 { 7820 if (gles_ver > 0) { 7821 caps->v1.glsl_level = 120; 7822 7823 if (gles_ver >= 31) 7824 caps->v1.glsl_level = 310; 7825 else if (gles_ver >= 30) 7826 caps->v1.glsl_level = 130; 7827 } 7828 7829 if (gl_ver > 0) { 7830 caps->v1.glsl_level = 130; 7831 7832 if (gl_ver == 31) 7833 caps->v1.glsl_level = 140; 7834 else if (gl_ver == 32) 7835 caps->v1.glsl_level = 150; 7836 else if (gl_ver == 33) 7837 caps->v1.glsl_level = 330; 7838 else if (gl_ver == 40) 7839 caps->v1.glsl_level = 400; 7840 else if (gl_ver == 41) 7841 caps->v1.glsl_level = 410; 7842 else if (gl_ver == 42) 7843 caps->v1.glsl_level = 420; 7844 else if (gl_ver >= 43) 7845 caps->v1.glsl_level = 430; 7846 } 7847 } 7848 7849 /* 7850 * Does all of the common caps setting, 7851 * if it dedects a early out returns true. 7852 */ 7853 static void vrend_renderer_fill_caps_v1(int gl_ver, int gles_ver, union virgl_caps *caps) 7854 { 7855 int i; 7856 GLint max; 7857 7858 /* 7859 * We can't fully support this feature on GLES, 7860 * but it is needed for OpenGL 2.1 so lie. 7861 */ 7862 caps->v1.bset.occlusion_query = 1; 7863 7864 /* Set supported prims here as we now know what shaders we support. */ 7865 caps->v1.prim_mask = (1 << PIPE_PRIM_POINTS) | (1 << PIPE_PRIM_LINES) | 7866 (1 << PIPE_PRIM_LINE_STRIP) | (1 << PIPE_PRIM_LINE_LOOP) | 7867 (1 << PIPE_PRIM_TRIANGLES) | (1 << PIPE_PRIM_TRIANGLE_STRIP) | 7868 (1 << PIPE_PRIM_TRIANGLE_FAN); 7869 7870 if (gl_ver > 0 && !vrend_state.use_core_profile) { 7871 caps->v1.bset.poly_stipple = 1; 7872 caps->v1.bset.color_clamping = 1; 7873 caps->v1.prim_mask |= (1 << PIPE_PRIM_QUADS) | 7874 (1 << PIPE_PRIM_QUAD_STRIP) | 7875 (1 << PIPE_PRIM_POLYGON); 7876 } 7877 7878 if (caps->v1.glsl_level >= 150) { 7879 caps->v1.prim_mask |= (1 << PIPE_PRIM_LINES_ADJACENCY) | 7880 (1 << PIPE_PRIM_LINE_STRIP_ADJACENCY) | 7881 (1 << PIPE_PRIM_TRIANGLES_ADJACENCY) | 7882 (1 << PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY); 7883 } 7884 if (caps->v1.glsl_level >= 400) 7885 caps->v1.prim_mask |= (1 << PIPE_PRIM_PATCHES); 7886 7887 if (epoxy_has_gl_extension("GL_ARB_vertex_type_10f_11f_11f_rev")) { 7888 int val = VIRGL_FORMAT_R11G11B10_FLOAT; 7889 uint32_t offset = val / 32; 7890 uint32_t index = val % 32; 7891 caps->v1.vertexbuffer.bitmask[offset] |= (1 << index); 7892 } 7893 7894 if (has_feature(feat_nv_conditional_render) || 7895 has_feature(feat_gl_conditional_render)) 7896 caps->v1.bset.conditional_render = 1; 7897 7898 if (has_feature(feat_indep_blend)) 7899 caps->v1.bset.indep_blend_enable = 1; 7900 7901 if (has_feature(feat_draw_instance)) 7902 caps->v1.bset.instanceid = 1; 7903 7904 if (has_feature(feat_ubo)) { 7905 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &max); 7906 vrend_state.max_uniform_blocks = max; 7907 caps->v1.max_uniform_blocks = max + 1; 7908 } 7909 7910 if (gl_ver >= 32) { 7911 caps->v1.bset.fragment_coord_conventions = 1; 7912 caps->v1.bset.depth_clip_disable = 1; 7913 caps->v1.bset.seamless_cube_map = 1; 7914 } else { 7915 if (epoxy_has_gl_extension("GL_ARB_fragment_coord_conventions")) 7916 caps->v1.bset.fragment_coord_conventions = 1; 7917 if (epoxy_has_gl_extension("GL_ARB_seamless_cube_map")) 7918 caps->v1.bset.seamless_cube_map = 1; 7919 } 7920 7921 if (epoxy_has_gl_extension("GL_AMD_seamless_cube_map_per_texture")) { 7922 caps->v1.bset.seamless_cube_map_per_texture = 1; 7923 } 7924 7925 if (has_feature(feat_texture_multisample)) 7926 caps->v1.bset.texture_multisample = 1; 7927 7928 if (has_feature(feat_tessellation)) 7929 caps->v1.bset.has_tessellation_shaders = 1; 7930 7931 if (has_feature(feat_sample_shading)) 7932 caps->v1.bset.has_sample_shading = 1; 7933 7934 if (has_feature(feat_indirect_draw)) 7935 caps->v1.bset.has_indirect_draw = 1; 7936 7937 if (has_feature(feat_indep_blend_func)) 7938 caps->v1.bset.indep_blend_func = 1; 7939 7940 if (has_feature(feat_cube_map_array)) 7941 caps->v1.bset.cube_map_array = 1; 7942 7943 if (gl_ver >= 40) { 7944 caps->v1.bset.texture_query_lod = 1; 7945 caps->v1.bset.has_fp64 = 1; 7946 } else { 7947 if (epoxy_has_gl_extension("GL_ARB_texture_query_lod")) 7948 caps->v1.bset.texture_query_lod = 1; 7949 /* need gpu shader 5 for bitfield insert */ 7950 if (epoxy_has_gl_extension("GL_ARB_gpu_shader_fp64") && 7951 epoxy_has_gl_extension("GL_ARB_gpu_shader5")) 7952 caps->v1.bset.has_fp64 = 1; 7953 } 7954 7955 if (has_feature(feat_base_instance)) 7956 caps->v1.bset.start_instance = 1; 7957 7958 if (epoxy_has_gl_extension("GL_ARB_shader_stencil_export")) { 7959 caps->v1.bset.shader_stencil_export = 1; 7960 } 7961 7962 if (has_feature(feat_conditional_render_inverted)) 7963 caps->v1.bset.conditional_render_inverted = 1; 7964 7965 if (gl_ver >= 45) { 7966 caps->v1.bset.has_cull = 1; 7967 caps->v1.bset.derivative_control = 1; 7968 } else { 7969 if (epoxy_has_gl_extension("GL_ARB_cull_distance")) 7970 caps->v1.bset.has_cull = 1; 7971 if (epoxy_has_gl_extension("GL_ARB_derivative_control")) 7972 caps->v1.bset.derivative_control = 1; 7973 } 7974 7975 if (has_feature(feat_polygon_offset_clamp)) 7976 caps->v1.bset.polygon_offset_clamp = 1; 7977 7978 if (has_feature(feat_transform_feedback_overflow_query)) 7979 caps->v1.bset.transform_feedback_overflow_query = 1; 7980 7981 if (epoxy_has_gl_extension("GL_EXT_texture_mirror_clamp") || 7982 epoxy_has_gl_extension("GL_ARB_texture_mirror_clamp_to_edge")) { 7983 caps->v1.bset.mirror_clamp = true; 7984 } 7985 7986 if (has_feature(feat_texture_array)) { 7987 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &max); 7988 caps->v1.max_texture_array_layers = max; 7989 } 7990 7991 /* we need tf3 so we can do gallium skip buffers */ 7992 if (has_feature(feat_transform_feedback)) { 7993 if (has_feature(feat_transform_feedback2)) 7994 caps->v1.bset.streamout_pause_resume = 1; 7995 7996 if (has_feature(feat_transform_feedback3)) { 7997 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max); 7998 caps->v1.max_streamout_buffers = max; 7999 } else if (gles_ver > 0) { 8000 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max); 8001 /* As with the earlier version of transform feedback this min 4. */ 8002 if (max >= 4) { 8003 caps->v1.max_streamout_buffers = 4; 8004 } 8005 } else 8006 caps->v1.max_streamout_buffers = 4; 8007 } 8008 8009 if (has_feature(feat_dual_src_blend)) { 8010 glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, &max); 8011 caps->v1.max_dual_source_render_targets = max; 8012 } 8013 8014 if (has_feature(feat_arb_or_gles_ext_texture_buffer)) { 8015 glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &max); 8016 caps->v1.max_tbo_size = max; 8017 } 8018 8019 if (has_feature(feat_texture_gather)) { 8020 if (gl_ver > 0) { 8021 glGetIntegerv(GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB, &max); 8022 caps->v1.max_texture_gather_components = max; 8023 } else { 8024 caps->v1.max_texture_gather_components = 4; 8025 } 8026 } 8027 8028 if (has_feature(feat_viewport_array)) { 8029 glGetIntegerv(GL_MAX_VIEWPORTS, &max); 8030 caps->v1.max_viewports = max; 8031 } else { 8032 caps->v1.max_viewports = 1; 8033 } 8034 8035 /* Common limits for all backends. */ 8036 caps->v1.max_render_targets = vrend_state.max_draw_buffers; 8037 8038 glGetIntegerv(GL_MAX_SAMPLES, &max); 8039 caps->v1.max_samples = max; 8040 8041 /* All of the formats are common. */ 8042 for (i = 0; i < VIRGL_FORMAT_MAX; i++) { 8043 uint32_t offset = i / 32; 8044 uint32_t index = i % 32; 8045 8046 if (tex_conv_table[i].internalformat != 0) { 8047 if (vrend_format_can_sample(i)) { 8048 caps->v1.sampler.bitmask[offset] |= (1 << index); 8049 if (vrend_format_can_render(i)) 8050 caps->v1.render.bitmask[offset] |= (1 << index); 8051 } 8052 } 8053 } 8054 8055 /* These are filled in by the init code, so are common. */ 8056 if (has_feature(feat_nv_prim_restart) || 8057 has_feature(feat_gl_prim_restart)) { 8058 caps->v1.bset.primitive_restart = 1; 8059 } 8060 } 8061 8062 static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_caps *caps) 8063 { 8064 GLint max; 8065 GLfloat range[2]; 8066 8067 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, range); 8068 caps->v2.min_aliased_point_size = range[0]; 8069 caps->v2.max_aliased_point_size = range[1]; 8070 8071 glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range); 8072 caps->v2.min_aliased_line_width = range[0]; 8073 caps->v2.max_aliased_line_width = range[1]; 8074 8075 if (gl_ver > 0) { 8076 glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE, range); 8077 caps->v2.min_smooth_point_size = range[0]; 8078 caps->v2.max_smooth_point_size = range[1]; 8079 8080 glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range); 8081 caps->v2.min_smooth_line_width = range[0]; 8082 caps->v2.max_smooth_line_width = range[1]; 8083 } 8084 8085 glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps->v2.max_texture_lod_bias); 8086 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, (GLint*)&caps->v2.max_vertex_attribs); 8087 glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &max); 8088 caps->v2.max_vertex_outputs = max / 4; 8089 8090 glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps->v2.min_texel_offset); 8091 glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &caps->v2.max_texel_offset); 8092 8093 glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, (GLint*)&caps->v2.uniform_buffer_offset_alignment); 8094 8095 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&caps->v2.max_texture_2d_size); 8096 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (GLint*)&caps->v2.max_texture_3d_size); 8097 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&caps->v2.max_texture_cube_size); 8098 8099 if (has_feature(feat_geometry_shader)) { 8100 glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, (GLint*)&caps->v2.max_geom_output_vertices); 8101 glGetIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, (GLint*)&caps->v2.max_geom_total_output_components); 8102 } 8103 8104 if (has_feature(feat_tessellation)) { 8105 glGetIntegerv(GL_MAX_TESS_PATCH_COMPONENTS, &max); 8106 caps->v2.max_shader_patch_varyings = max / 4; 8107 } else 8108 caps->v2.max_shader_patch_varyings = 0; 8109 8110 if (has_feature(feat_texture_gather)) { 8111 glGetIntegerv(GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET, &caps->v2.min_texture_gather_offset); 8112 glGetIntegerv(GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET, &caps->v2.max_texture_gather_offset); 8113 } 8114 8115 if (gl_ver >= 43) { 8116 glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, (GLint*)&caps->v2.texture_buffer_offset_alignment); 8117 } 8118 8119 if (has_feature(feat_ssbo)) { 8120 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, (GLint*)&caps->v2.shader_buffer_offset_alignment); 8121 8122 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &max); 8123 if (max > PIPE_MAX_SHADER_BUFFERS) 8124 max = PIPE_MAX_SHADER_BUFFERS; 8125 caps->v2.max_shader_buffer_other_stages = max; 8126 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &max); 8127 if (max > PIPE_MAX_SHADER_BUFFERS) 8128 max = PIPE_MAX_SHADER_BUFFERS; 8129 caps->v2.max_shader_buffer_frag_compute = max; 8130 } 8131 8132 if (has_feature(feat_images)) { 8133 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max); 8134 if (max > PIPE_MAX_SHADER_IMAGES) 8135 max = PIPE_MAX_SHADER_IMAGES; 8136 caps->v2.max_shader_image_other_stages = max; 8137 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max); 8138 if (max > PIPE_MAX_SHADER_IMAGES) 8139 max = PIPE_MAX_SHADER_IMAGES; 8140 caps->v2.max_shader_image_frag_compute = max; 8141 8142 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, (GLint*)&caps->v2.max_image_samples); 8143 } 8144 8145 if (has_feature(feat_storage_multisample)) 8146 caps->v1.max_samples = vrend_renderer_query_multisample_caps(caps->v1.max_samples, &caps->v2); 8147 8148 caps->v2.capability_bits |= VIRGL_CAP_TGSI_INVARIANT | VIRGL_CAP_SET_MIN_SAMPLES | VIRGL_CAP_TGSI_PRECISE; 8149 8150 if (gl_ver >= 44 || gles_ver >= 31) 8151 glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, (GLint*)&caps->v2.max_vertex_attrib_stride); 8152 8153 if (has_feature(feat_compute_shader)) { 8154 glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, (GLint*)&caps->v2.max_compute_work_group_invocations); 8155 glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, (GLint*)&caps->v2.max_compute_shared_memory_size); 8156 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, (GLint*)&caps->v2.max_compute_grid_size[0]); 8157 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, (GLint*)&caps->v2.max_compute_grid_size[1]); 8158 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, (GLint*)&caps->v2.max_compute_grid_size[2]); 8159 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, (GLint*)&caps->v2.max_compute_block_size[0]); 8160 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, (GLint*)&caps->v2.max_compute_block_size[1]); 8161 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, (GLint*)&caps->v2.max_compute_block_size[2]); 8162 8163 caps->v2.capability_bits |= VIRGL_CAP_COMPUTE_SHADER; 8164 } 8165 8166 if (has_feature(feat_fb_no_attach)) 8167 caps->v2.capability_bits |= VIRGL_CAP_FB_NO_ATTACH; 8168 8169 if (has_feature(feat_texture_view)) 8170 caps->v2.capability_bits |= VIRGL_CAP_TEXTURE_VIEW; 8171 8172 if (has_feature(feat_txqs)) 8173 caps->v2.capability_bits |= VIRGL_CAP_TXQS; 8174 8175 if (has_feature(feat_barrier)) 8176 caps->v2.capability_bits |= VIRGL_CAP_MEMORY_BARRIER; 8177 8178 if (has_feature(feat_copy_image)) 8179 caps->v2.capability_bits |= VIRGL_CAP_COPY_IMAGE; 8180 8181 if (has_feature(feat_robust_buffer_access)) 8182 caps->v2.capability_bits |= VIRGL_CAP_ROBUST_BUFFER_ACCESS; 8183 8184 if (has_feature(feat_framebuffer_fetch)) 8185 caps->v2.capability_bits |= VIRGL_CAP_TGSI_FBFETCH; 8186 8187 if (has_feature(feat_shader_clock)) 8188 caps->v2.capability_bits |= VIRGL_CAP_SHADER_CLOCK; 8189 8190 if (has_feature(feat_texture_barrier)) 8191 caps->v2.capability_bits |= VIRGL_CAP_TEXTURE_BARRIER; 8192 } 8193 8194 void vrend_renderer_fill_caps(uint32_t set, UNUSED uint32_t version, 8195 union virgl_caps *caps) 8196 { 8197 int gl_ver, gles_ver; 8198 bool fill_capset2 = false; 8199 8200 if (!caps) 8201 return; 8202 8203 if (set > 2) { 8204 caps->max_version = 0; 8205 return; 8206 } 8207 8208 if (set == 1) { 8209 memset(caps, 0, sizeof(struct virgl_caps_v1)); 8210 caps->max_version = 1; 8211 } else if (set == 2) { 8212 memset(caps, 0, sizeof(*caps)); 8213 caps->max_version = 2; 8214 fill_capset2 = true; 8215 } 8216 8217 if (vrend_state.use_gles) { 8218 gles_ver = epoxy_gl_version(); 8219 gl_ver = 0; 8220 } else { 8221 gles_ver = 0; 8222 gl_ver = epoxy_gl_version(); 8223 } 8224 8225 vrend_fill_caps_glsl_version(gl_ver, gles_ver, caps); 8226 vrend_renderer_fill_caps_v1(gl_ver, gles_ver, caps); 8227 8228 if (!fill_capset2) 8229 return; 8230 8231 vrend_renderer_fill_caps_v2(gl_ver, gles_ver, caps); 8232 } 8233 8234 GLint64 vrend_renderer_get_timestamp(void) 8235 { 8236 GLint64 v; 8237 glGetInteger64v(GL_TIMESTAMP, &v); 8238 return v; 8239 } 8240 8241 void *vrend_renderer_get_cursor_contents(uint32_t res_handle, uint32_t *width, uint32_t *height) 8242 { 8243 GLenum format, type; 8244 struct vrend_resource *res; 8245 int blsize; 8246 char *data, *data2; 8247 int size; 8248 uint h; 8249 8250 res = vrend_resource_lookup(res_handle, 0); 8251 if (!res) 8252 return NULL; 8253 8254 if (res->base.width0 > 128 || res->base.height0 > 128) 8255 return NULL; 8256 8257 if (res->target != GL_TEXTURE_2D) 8258 return NULL; 8259 8260 if (width) 8261 *width = res->base.width0; 8262 if (height) 8263 *height = res->base.height0; 8264 format = tex_conv_table[res->base.format].glformat; 8265 type = tex_conv_table[res->base.format].gltype; 8266 blsize = util_format_get_blocksize(res->base.format); 8267 size = util_format_get_nblocks(res->base.format, res->base.width0, res->base.height0) * blsize; 8268 data = malloc(size); 8269 data2 = malloc(size); 8270 8271 if (!data || !data2) { 8272 free(data); 8273 free(data2); 8274 return NULL; 8275 } 8276 8277 if (has_feature(feat_arb_robustness)) { 8278 glBindTexture(res->target, res->id); 8279 glGetnTexImageARB(res->target, 0, format, type, size, data); 8280 } else if (vrend_state.use_gles) { 8281 GLuint fb_id; 8282 8283 if (res->readback_fb_id == 0 || res->readback_fb_level != 0 || res->readback_fb_z != 0) { 8284 8285 if (res->readback_fb_id) 8286 glDeleteFramebuffers(1, &res->readback_fb_id); 8287 8288 glGenFramebuffers(1, &fb_id); 8289 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_id); 8290 8291 vrend_fb_bind_texture(res, 0, 0, 0); 8292 8293 res->readback_fb_id = fb_id; 8294 res->readback_fb_level = 0; 8295 res->readback_fb_z = 0; 8296 } else { 8297 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, res->readback_fb_id); 8298 } 8299 8300 if (has_feature(feat_arb_robustness)) { 8301 glReadnPixelsARB(0, 0, *width, *height, format, type, size, data); 8302 } else if (has_feature(feat_gles_khr_robustness)) { 8303 glReadnPixelsKHR(0, 0, *width, *height, format, type, size, data); 8304 } else { 8305 glReadPixels(0, 0, *width, *height, format, type, data); 8306 } 8307 8308 } else { 8309 glBindTexture(res->target, res->id); 8310 glGetTexImage(res->target, 0, format, type, data); 8311 } 8312 8313 for (h = 0; h < res->base.height0; h++) { 8314 uint32_t doff = (res->base.height0 - h - 1) * res->base.width0 * blsize; 8315 uint32_t soff = h * res->base.width0 * blsize; 8316 8317 memcpy(data2 + doff, data + soff, res->base.width0 * blsize); 8318 } 8319 free(data); 8320 8321 return data2; 8322 } 8323 8324 void vrend_renderer_force_ctx_0(void) 8325 { 8326 struct vrend_context *ctx0 = vrend_lookup_renderer_ctx(0); 8327 vrend_state.current_ctx = NULL; 8328 vrend_state.current_hw_ctx = NULL; 8329 vrend_hw_switch_context(ctx0, true); 8330 vrend_clicbs->make_current(0, ctx0->sub->gl_context); 8331 } 8332 8333 void vrend_renderer_get_rect(int res_handle, struct iovec *iov, unsigned int num_iovs, 8334 uint32_t offset, int x, int y, int width, int height) 8335 { 8336 struct vrend_resource *res = vrend_resource_lookup(res_handle, 0); 8337 struct vrend_transfer_info transfer_info; 8338 struct pipe_box box; 8339 int elsize; 8340 8341 memset(&transfer_info, 0, sizeof(transfer_info)); 8342 8343 elsize = util_format_get_blocksize(res->base.format); 8344 box.x = x; 8345 box.y = y; 8346 box.z = 0; 8347 box.width = width; 8348 box.height = height; 8349 box.depth = 1; 8350 8351 transfer_info.box = &box; 8352 8353 transfer_info.stride = util_format_get_nblocksx(res->base.format, res->base.width0) * elsize; 8354 transfer_info.offset = offset; 8355 transfer_info.handle = res->handle; 8356 transfer_info.iovec = iov; 8357 transfer_info.iovec_cnt = num_iovs; 8358 vrend_renderer_transfer_iov(&transfer_info, VREND_TRANSFER_READ); 8359 } 8360 8361 void vrend_renderer_attach_res_ctx(int ctx_id, int resource_id) 8362 { 8363 struct vrend_context *ctx = vrend_lookup_renderer_ctx(ctx_id); 8364 struct vrend_resource *res; 8365 8366 if (!ctx) 8367 return; 8368 8369 res = vrend_resource_lookup(resource_id, 0); 8370 if (!res) 8371 return; 8372 8373 vrend_object_insert_nofree(ctx->res_hash, res, sizeof(*res), resource_id, 1, false); 8374 } 8375 8376 static void vrend_renderer_detach_res_ctx_p(struct vrend_context *ctx, int res_handle) 8377 { 8378 struct vrend_resource *res; 8379 res = vrend_object_lookup(ctx->res_hash, res_handle, 1); 8380 if (!res) 8381 return; 8382 8383 vrend_object_remove(ctx->res_hash, res_handle, 1); 8384 } 8385 8386 void vrend_renderer_detach_res_ctx(int ctx_id, int res_handle) 8387 { 8388 struct vrend_context *ctx = vrend_lookup_renderer_ctx(ctx_id); 8389 if (!ctx) 8390 return; 8391 vrend_renderer_detach_res_ctx_p(ctx, res_handle); 8392 } 8393 8394 static struct vrend_resource *vrend_renderer_ctx_res_lookup(struct vrend_context *ctx, int res_handle) 8395 { 8396 struct vrend_resource *res = vrend_object_lookup(ctx->res_hash, res_handle, 1); 8397 8398 return res; 8399 } 8400 8401 int vrend_renderer_resource_get_info(int res_handle, 8402 struct vrend_renderer_resource_info *info) 8403 { 8404 struct vrend_resource *res; 8405 int elsize; 8406 8407 if (!info) 8408 return EINVAL; 8409 res = vrend_resource_lookup(res_handle, 0); 8410 if (!res) 8411 return EINVAL; 8412 8413 elsize = util_format_get_blocksize(res->base.format); 8414 8415 info->handle = res_handle; 8416 info->tex_id = res->id; 8417 info->width = res->base.width0; 8418 info->height = res->base.height0; 8419 info->depth = res->base.depth0; 8420 info->format = res->base.format; 8421 info->flags = res->y_0_top ? VIRGL_RESOURCE_Y_0_TOP : 0; 8422 info->stride = util_format_get_nblocksx(res->base.format, u_minify(res->base.width0, 0)) * elsize; 8423 8424 return 0; 8425 } 8426 8427 void vrend_renderer_get_cap_set(uint32_t cap_set, uint32_t *max_ver, 8428 uint32_t *max_size) 8429 { 8430 switch (cap_set) { 8431 case VREND_CAP_SET: 8432 *max_ver = 1; 8433 *max_size = sizeof(struct virgl_caps_v1); 8434 break; 8435 case VREND_CAP_SET2: 8436 /* we should never need to increase this - it should be possible to just grow virgl_caps */ 8437 *max_ver = 2; 8438 *max_size = sizeof(struct virgl_caps_v2); 8439 break; 8440 default: 8441 *max_ver = 0; 8442 *max_size = 0; 8443 break; 8444 } 8445 } 8446 8447 void vrend_renderer_create_sub_ctx(struct vrend_context *ctx, int sub_ctx_id) 8448 { 8449 struct vrend_sub_context *sub; 8450 struct virgl_gl_ctx_param ctx_params; 8451 GLuint i; 8452 8453 LIST_FOR_EACH_ENTRY(sub, &ctx->sub_ctxs, head) { 8454 if (sub->sub_ctx_id == sub_ctx_id) { 8455 return; 8456 } 8457 } 8458 8459 sub = CALLOC_STRUCT(vrend_sub_context); 8460 if (!sub) 8461 return; 8462 8463 ctx_params.shared = (ctx->ctx_id == 0 && sub_ctx_id == 0) ? false : true; 8464 ctx_params.major_ver = vrend_state.gl_major_ver; 8465 ctx_params.minor_ver = vrend_state.gl_minor_ver; 8466 sub->gl_context = vrend_clicbs->create_gl_context(0, &ctx_params); 8467 vrend_clicbs->make_current(0, sub->gl_context); 8468 8469 /* enable if vrend_renderer_init function has done it as well */ 8470 if (has_feature(feat_debug_cb)) { 8471 glDebugMessageCallback(vrend_debug_cb, NULL); 8472 glEnable(GL_DEBUG_OUTPUT); 8473 glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 8474 } 8475 8476 sub->sub_ctx_id = sub_ctx_id; 8477 8478 /* initialize the depth far_val to 1 */ 8479 for (i = 0; i < PIPE_MAX_VIEWPORTS; i++) { 8480 sub->vps[i].far_val = 1.0; 8481 } 8482 8483 if (!has_feature(feat_gles31_vertex_attrib_binding)) { 8484 glGenVertexArrays(1, &sub->vaoid); 8485 glBindVertexArray(sub->vaoid); 8486 } 8487 8488 glGenFramebuffers(1, &sub->fb_id); 8489 glGenFramebuffers(2, sub->blit_fb_ids); 8490 8491 list_inithead(&sub->programs); 8492 list_inithead(&sub->streamout_list); 8493 8494 sub->object_hash = vrend_object_init_ctx_table(); 8495 8496 ctx->sub = sub; 8497 list_add(&sub->head, &ctx->sub_ctxs); 8498 if (sub_ctx_id == 0) 8499 ctx->sub0 = sub; 8500 } 8501 8502 void vrend_renderer_destroy_sub_ctx(struct vrend_context *ctx, int sub_ctx_id) 8503 { 8504 struct vrend_sub_context *sub, *tofree = NULL; 8505 8506 /* never destroy sub context id 0 */ 8507 if (sub_ctx_id == 0) 8508 return; 8509 8510 LIST_FOR_EACH_ENTRY(sub, &ctx->sub_ctxs, head) { 8511 if (sub->sub_ctx_id == sub_ctx_id) { 8512 tofree = sub; 8513 } 8514 } 8515 8516 if (tofree) { 8517 if (ctx->sub == tofree) { 8518 ctx->sub = ctx->sub0; 8519 vrend_clicbs->make_current(0, ctx->sub->gl_context); 8520 } 8521 vrend_destroy_sub_context(tofree); 8522 } 8523 } 8524 8525 void vrend_renderer_set_sub_ctx(struct vrend_context *ctx, int sub_ctx_id) 8526 { 8527 struct vrend_sub_context *sub; 8528 /* find the sub ctx */ 8529 8530 if (ctx->sub && ctx->sub->sub_ctx_id == sub_ctx_id) 8531 return; 8532 8533 LIST_FOR_EACH_ENTRY(sub, &ctx->sub_ctxs, head) { 8534 if (sub->sub_ctx_id == sub_ctx_id) { 8535 ctx->sub = sub; 8536 vrend_clicbs->make_current(0, sub->gl_context); 8537 break; 8538 } 8539 } 8540 } 8541 8542 static void vrend_reset_fences(void) 8543 { 8544 struct vrend_fence *fence, *stor; 8545 8546 if (vrend_state.sync_thread) 8547 pipe_mutex_lock(vrend_state.fence_mutex); 8548 8549 LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &vrend_state.fence_list, fences) { 8550 free_fence_locked(fence); 8551 } 8552 8553 if (vrend_state.sync_thread) 8554 pipe_mutex_unlock(vrend_state.fence_mutex); 8555 } 8556 8557 void vrend_renderer_reset(void) 8558 { 8559 if (vrend_state.sync_thread) { 8560 vrend_free_sync_thread(); 8561 vrend_state.stop_sync_thread = false; 8562 } 8563 vrend_reset_fences(); 8564 vrend_decode_reset(false); 8565 vrend_object_fini_resource_table(); 8566 vrend_decode_reset(true); 8567 vrend_object_init_resource_table(); 8568 vrend_renderer_context_create_internal(0, 0, NULL); 8569 } 8570 8571 int vrend_renderer_get_poll_fd(void) 8572 { 8573 if (!vrend_state.inited) 8574 return -1; 8575 8576 return vrend_state.eventfd; 8577 } 8578