void vrend_get_query_result_qbo(struct vrend_context *ctx, uint32_t handle,
                                uint32_t qbo_handle,
                                uint32_t wait, uint32_t result_type, uint32_t offset,
                                int32_t index)
{
  struct vrend_query *q;
  struct vrend_resource *res;

  if (!has_feature(feat_qbo))
     return;

  q = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_QUERY);
  if (!q)
     return;

  res = vrend_renderer_ctx_res_lookup(ctx, qbo_handle);
  if (!res) {
     vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, qbo_handle);
     return;
  }

  VREND_DEBUG(dbg_query, ctx, "Get query result from Query:%d\n", q->id);

  GLenum qtype;

  if (index == -1)
     qtype = GL_QUERY_RESULT_AVAILABLE;
  else
     qtype = wait ? GL_QUERY_RESULT : GL_QUERY_RESULT_NO_WAIT;

  if (!q->fake_samples_passed) {
     glBindBuffer(GL_QUERY_BUFFER, res->id);
     switch ((enum pipe_query_value_type)result_type) {
     case PIPE_QUERY_TYPE_I32:
        glGetQueryObjectiv(q->id, qtype, buffer_offset(offset));
        break;
     case PIPE_QUERY_TYPE_U32:
        glGetQueryObjectuiv(q->id, qtype, buffer_offset(offset));
        break;
     case PIPE_QUERY_TYPE_I64:
        glGetQueryObjecti64v(q->id, qtype, buffer_offset(offset));
        break;
     case PIPE_QUERY_TYPE_U64:
        glGetQueryObjectui64v(q->id, qtype, buffer_offset(offset));
        break;
     }
  } else {
     VREND_DEBUG(dbg_query, ctx, "Was emulating GL_PIXELS_PASSED by GL_ANY_PIXELS_PASSED, artifically upscaling the result\n");
     /* The application expects a sample count but we have only a boolean
      * so we blow the result up by 1/10 of the screen space to make sure the
      * app doesn't think only one sample passed. */
     vrend_update_oq_samples_multiplier(ctx);
     switch ((enum pipe_query_value_type)result_type) {
     case PIPE_QUERY_TYPE_I32: {
        GLint value;
        glGetQueryObjectiv(q->id, qtype, &value);
        COPY_QUERY_RESULT_TO_BUFFER(q->id, offset, value, 4, ctx->sub->fake_occlusion_query_samples_passed_multiplier);
        break;
     }
     case PIPE_QUERY_TYPE_U32: {
        GLuint value;
        glGetQueryObjectuiv(q->id, qtype, &value);
        COPY_QUERY_RESULT_TO_BUFFER(q->id, offset, value, 4, ctx->sub->fake_occlusion_query_samples_passed_multiplier);
        break;
     }
     case PIPE_QUERY_TYPE_I64: {
        GLint64 value;
        glGetQueryObjecti64v(q->id, qtype, &value);
        COPY_QUERY_RESULT_TO_BUFFER(q->id, offset, value, 8, ctx->sub->fake_occlusion_query_samples_passed_multiplier);
        break;
     }
     case PIPE_QUERY_TYPE_U64: {
        GLuint64 value;
        glGetQueryObjectui64v(q->id, qtype, &value);
        COPY_QUERY_RESULT_TO_BUFFER(q->id, offset, value, 8, ctx->sub->fake_occlusion_query_samples_passed_multiplier);
        break;
     }
     }


  }

  glBindBuffer(GL_QUERY_BUFFER, 0);
}
void vrend_get_query_result_qbo(struct vrend_context *ctx, uint32_t handle,
                                uint32_t qbo_handle,
                                uint32_t wait, uint32_t result_type, uint32_t offset,
                                int32_t index)
{
  struct vrend_query *q;
  struct vrend_resource *res;

  if (!has_feature(feat_qbo))
     return;

  q = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_QUERY);
  if (!q)
     return;

  res = vrend_renderer_ctx_res_lookup(ctx, qbo_handle);
  if (!res) {
     vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, qbo_handle);
     return;
  }

  VREND_DEBUG(dbg_query, ctx, "Get query result from Query:%d\n", q->id);

  GLenum qtype;

  if (index == -1)
     qtype = GL_QUERY_RESULT_AVAILABLE;
  else
     qtype = wait ? GL_QUERY_RESULT : GL_QUERY_RESULT_NO_WAIT;

  if (!q->fake_samples_passed) {
     glBindBuffer(GL_QUERY_BUFFER, res->id);
     switch ((enum pipe_query_value_type)result_type) {
     case PIPE_QUERY_TYPE_I32:
        glGetQueryObjectiv(q->id, qtype, buffer_offset(offset));
        break;
     case PIPE_QUERY_TYPE_U32:
        glGetQueryObjectuiv(q->id, qtype, buffer_offset(offset));
        break;
     case PIPE_QUERY_TYPE_I64:
        glGetQueryObjecti64v(q->id, qtype, buffer_offset(offset));
        break;
     case PIPE_QUERY_TYPE_U64:
        glGetQueryObjectui64v(q->id, qtype, buffer_offset(offset));
        break;
     }
  } else {
     VREND_DEBUG(dbg_query, ctx, "Was emulating GL_PIXELS_PASSED by GL_ANY_PIXELS_PASSED, artifically upscaling the result\n");
      
     vrend_update_oq_samples_multiplier(ctx);
     switch ((enum pipe_query_value_type)result_type) {
     case PIPE_QUERY_TYPE_I32: {
        GLint value;
        glGetQueryObjectiv(q->id, qtype, &value);
        COPY_QUERY_RESULT_TO_BUFFER(q->id, offset, value, 4, ctx->sub->fake_occlusion_query_samples_passed_multiplier);
        break;
     }
     case PIPE_QUERY_TYPE_U32: {
        GLuint value;
        glGetQueryObjectuiv(q->id, qtype, &value);
        COPY_QUERY_RESULT_TO_BUFFER(q->id, offset, value, 4, ctx->sub->fake_occlusion_query_samples_passed_multiplier);
        break;
     }
     case PIPE_QUERY_TYPE_I64: {
        GLint64 value;
        glGetQueryObjecti64v(q->id, qtype, &value);
        COPY_QUERY_RESULT_TO_BUFFER(q->id, offset, value, 8, ctx->sub->fake_occlusion_query_samples_passed_multiplier);
        break;
     }
     case PIPE_QUERY_TYPE_U64: {
        GLuint64 value;
        glGetQueryObjectui64v(q->id, qtype, &value);
        COPY_QUERY_RESULT_TO_BUFFER(q->id, offset, value, 8, ctx->sub->fake_occlusion_query_samples_passed_multiplier);
        break;
     }
     }


  }

  glBindBuffer(GL_QUERY_BUFFER, 0);
}