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