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