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