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