int vrend_create_query(struct vrend_context *ctx, uint32_t handle,
                       uint32_t query_type, uint32_t query_index,
                       uint32_t res_handle, UNUSED uint32_t offset)
{
   struct vrend_query *q;
   struct vrend_resource *res;
   uint32_t ret_handle;
   bool fake_samples_passed = false;
   res = vrend_renderer_ctx_res_lookup(ctx, res_handle);
   if (!res || !has_bit(res->storage_bits, VREND_STORAGE_HOST_SYSTEM_MEMORY)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle);
      return EINVAL;
   }

   /* If we don't have ARB_occlusion_query, at least try to fake GL_SAMPLES_PASSED
    * by using GL_ANY_SAMPLES_PASSED (i.e. EXT_occlusion_query_boolean) */
   if (!has_feature(feat_occlusion_query) && query_type == PIPE_QUERY_OCCLUSION_COUNTER) {
      VREND_DEBUG(dbg_query, ctx, "GL_SAMPLES_PASSED not supported will try GL_ANY_SAMPLES_PASSED\n");
      query_type = PIPE_QUERY_OCCLUSION_PREDICATE;
      fake_samples_passed = true;
   }

   if (query_type == PIPE_QUERY_OCCLUSION_PREDICATE &&
       !has_feature(feat_occlusion_query_boolean)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_GL_ANY_SAMPLES_PASSED, res_handle);
      return EINVAL;
   }

   q = CALLOC_STRUCT(vrend_query);
   if (!q)
      return ENOMEM;

   list_inithead(&q->waiting_queries);
   q->type = query_type;
   q->index = query_index;
   q->ctx = ctx;
   q->fake_samples_passed = fake_samples_passed;

   vrend_resource_reference(&q->res, res);

   switch (q->type) {
   case PIPE_QUERY_OCCLUSION_COUNTER:
      q->gltype = GL_SAMPLES_PASSED_ARB;
      break;
   case PIPE_QUERY_OCCLUSION_PREDICATE:
      if (has_feature(feat_occlusion_query_boolean)) {
         q->gltype = GL_ANY_SAMPLES_PASSED;
         break;
      } else
         return EINVAL;
   case PIPE_QUERY_TIMESTAMP:
      if (!has_feature(feat_timer_query))
         return EINVAL;
      q->gltype = GL_TIMESTAMP;
      break;
   case PIPE_QUERY_TIME_ELAPSED:
      if (!has_feature(feat_timer_query))
         return EINVAL;
      q->gltype = GL_TIME_ELAPSED;
      break;
   case PIPE_QUERY_PRIMITIVES_GENERATED:
      q->gltype = GL_PRIMITIVES_GENERATED;
      break;
   case PIPE_QUERY_PRIMITIVES_EMITTED:
      q->gltype = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN;
      break;
   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
      q->gltype = GL_ANY_SAMPLES_PASSED_CONSERVATIVE;
      break;
   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
      if (!has_feature(feat_transform_feedback_overflow_query))
         return EINVAL;
      q->gltype = GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB;
      break;
   case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
      if (!has_feature(feat_transform_feedback_overflow_query))
         return EINVAL;
      q->gltype = GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB;
      break;
   default:
      vrend_printf("unknown query object received %d\n", q->type);
      break;
   }

   glGenQueries(1, &q->id);

   ret_handle = vrend_renderer_object_insert(ctx, q, handle,
                                             VIRGL_OBJECT_QUERY);
   if (!ret_handle) {
      FREE(q);
      return ENOMEM;
   }
   return 0;
}
int vrend_create_query(struct vrend_context *ctx, uint32_t handle,
                       uint32_t query_type, uint32_t query_index,
                       uint32_t res_handle, UNUSED uint32_t offset)
{
   struct vrend_query *q;
   struct vrend_resource *res;
   uint32_t ret_handle;
   bool fake_samples_passed = false;
   res = vrend_renderer_ctx_res_lookup(ctx, res_handle);
   if (!res || !has_bit(res->storage_bits, VREND_STORAGE_HOST_SYSTEM_MEMORY)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, res_handle);
      return EINVAL;
   }

    
   if (!has_feature(feat_occlusion_query) && query_type == PIPE_QUERY_OCCLUSION_COUNTER) {
      VREND_DEBUG(dbg_query, ctx, "GL_SAMPLES_PASSED not supported will try GL_ANY_SAMPLES_PASSED\n");
      query_type = PIPE_QUERY_OCCLUSION_PREDICATE;
      fake_samples_passed = true;
   }

   if (query_type == PIPE_QUERY_OCCLUSION_PREDICATE &&
       !has_feature(feat_occlusion_query_boolean)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_GL_ANY_SAMPLES_PASSED, res_handle);
      return EINVAL;
   }

   q = CALLOC_STRUCT(vrend_query);
   if (!q)
      return ENOMEM;

   list_inithead(&q->waiting_queries);
   q->type = query_type;
   q->index = query_index;
   q->ctx = ctx;
   q->fake_samples_passed = fake_samples_passed;

   vrend_resource_reference(&q->res, res);

   switch (q->type) {
   case PIPE_QUERY_OCCLUSION_COUNTER:
      q->gltype = GL_SAMPLES_PASSED_ARB;
      break;
   case PIPE_QUERY_OCCLUSION_PREDICATE:
      if (has_feature(feat_occlusion_query_boolean)) {
         q->gltype = GL_ANY_SAMPLES_PASSED;
         break;
      } else
         return EINVAL;
   case PIPE_QUERY_TIMESTAMP:
      if (!has_feature(feat_timer_query))
         return EINVAL;
      q->gltype = GL_TIMESTAMP;
      break;
   case PIPE_QUERY_TIME_ELAPSED:
      if (!has_feature(feat_timer_query))
         return EINVAL;
      q->gltype = GL_TIME_ELAPSED;
      break;
   case PIPE_QUERY_PRIMITIVES_GENERATED:
      q->gltype = GL_PRIMITIVES_GENERATED;
      break;
   case PIPE_QUERY_PRIMITIVES_EMITTED:
      q->gltype = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN;
      break;
   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
      q->gltype = GL_ANY_SAMPLES_PASSED_CONSERVATIVE;
      break;
   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
      if (!has_feature(feat_transform_feedback_overflow_query))
         return EINVAL;
      q->gltype = GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB;
      break;
   case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
      if (!has_feature(feat_transform_feedback_overflow_query))
         return EINVAL;
      q->gltype = GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB;
      break;
   default:
      vrend_printf("unknown query object received %d\n", q->type);
      break;
   }

   glGenQueries(1, &q->id);

   ret_handle = vrend_renderer_object_insert(ctx, q, handle,
                                             VIRGL_OBJECT_QUERY);
   if (!ret_handle) {
      FREE(q);
      return ENOMEM;
   }
   return 0;
}