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