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