xref: /aosp_15_r20/external/virglrenderer/src/vrend_renderer.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
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, &param);
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 = &gt->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