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