+ return PIPE_OK;
+}
+
+static enum pipe_error
+begin_query_vgpu9(struct svga_context *svga, struct svga_query *sq)
+{
+ struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+ enum pipe_error ret = PIPE_OK;
+
+ if (sq->queryResult->state == SVGA3D_QUERYSTATE_PENDING) {
+ /* The application doesn't care for the pending query result.
+ * We cannot let go of the existing buffer and just get a new one
+ * because its storage may be reused for other purposes and clobbered
+ * by the host when it determines the query result. So the only
+ * option here is to wait for the existing query's result -- not a
+ * big deal, given that no sane application would do this.
+ */
+ uint64_t result;
+ svga_get_query_result(&svga->pipe, &sq->base, TRUE, (void*)&result);
+ assert(sq->queryResult->state != SVGA3D_QUERYSTATE_PENDING);
+ }
+
+ sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
+ sws->fence_reference(sws, &sq->fence, NULL);
+
+ ret = SVGA3D_BeginQuery(svga->swc, sq->svga_type);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_BeginQuery(svga->swc, sq->svga_type);
+ }
+ return ret;
+}
+
+static enum pipe_error
+end_query_vgpu9(struct svga_context *svga, struct svga_query *sq)
+{
+ enum pipe_error ret = PIPE_OK;
+
+ /* Set to PENDING before sending EndQuery. */
+ sq->queryResult->state = SVGA3D_QUERYSTATE_PENDING;
+
+ ret = SVGA3D_EndQuery(svga->swc, sq->svga_type, sq->hwbuf);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_EndQuery(svga->swc, sq->svga_type, sq->hwbuf);
+ }
+ return ret;
+}
+
+static bool
+get_query_result_vgpu9(struct svga_context *svga, struct svga_query *sq,
+ bool wait, uint64_t *result)
+{
+ struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+ enum pipe_error ret;
+ SVGA3dQueryState state;
+
+ if (!sq->fence) {
+ /* The query status won't be updated by the host unless
+ * SVGA_3D_CMD_WAIT_FOR_QUERY is emitted. Unfortunately this will cause
+ * a synchronous wait on the host.
+ */
+ ret = SVGA3D_WaitForQuery(svga->swc, sq->svga_type, sq->hwbuf);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_WaitForQuery(svga->swc, sq->svga_type, sq->hwbuf);
+ }
+ assert (ret == PIPE_OK);
+ svga_context_flush(svga, &sq->fence);
+ assert(sq->fence);
+ }
+
+ state = sq->queryResult->state;
+ if (state == SVGA3D_QUERYSTATE_PENDING) {
+ if (!wait)
+ return false;
+ sws->fence_finish(sws, sq->fence, PIPE_TIMEOUT_INFINITE,
+ SVGA_FENCE_FLAG_QUERY);
+ state = sq->queryResult->state;
+ }
+
+ assert(state == SVGA3D_QUERYSTATE_SUCCEEDED ||
+ state == SVGA3D_QUERYSTATE_FAILED);
+
+ *result = (uint64_t)sq->queryResult->result32;
+ return true;
+}
+
+
+/**
+ * VGPU10
+ *
+ * There is one query mob allocated for each context to be shared by all
+ * query types. The mob is used to hold queries's state and result. Since
+ * each query result type is of different length, to ease the query allocation
+ * management, the mob is divided into memory blocks. Each memory block
+ * will hold queries of the same type. Multiple memory blocks can be allocated
+ * for a particular query type.
+ *
+ * Currently each memory block is of 184 bytes. We support up to 128
+ * memory blocks. The query memory size is arbitrary right now.
+ * Each occlusion query takes about 8 bytes. One memory block can accomodate
+ * 23 occlusion queries. 128 of those blocks can support up to 2944 occlusion
+ * queries. That seems reasonable for now. If we think this limit is
+ * not enough, we can increase the limit or try to grow the mob in runtime.
+ * Note, SVGA device does not impose one mob per context for queries,
+ * we could allocate multiple mobs for queries; however, wddm KMD does not
+ * currently support that.
+ *
+ * Also note that the GL guest driver does not issue any of the
+ * following commands: DXMoveQuery, DXBindAllQuery & DXReadbackAllQuery.
+ */
+#define SVGA_QUERY_MEM_BLOCK_SIZE (sizeof(SVGADXQueryResultUnion) * 2)
+#define SVGA_QUERY_MEM_SIZE (128 * SVGA_QUERY_MEM_BLOCK_SIZE)
+
+struct svga_qmem_alloc_entry
+{
+ unsigned start_offset; /* start offset of the memory block */
+ unsigned block_index; /* block index of the memory block */
+ unsigned query_size; /* query size in this memory block */
+ unsigned nquery; /* number of queries allocated */
+ struct util_bitmask *alloc_mask; /* allocation mask */
+ struct svga_qmem_alloc_entry *next; /* next memory block */
+};
+
+
+/**
+ * Allocate a memory block from the query object memory
+ * \return -1 if out of memory, else index of the query memory block
+ */
+static int
+allocate_query_block(struct svga_context *svga)
+{
+ int index;
+ unsigned offset;
+
+ /* Find the next available query block */
+ index = util_bitmask_add(svga->gb_query_alloc_mask);
+
+ if (index == UTIL_BITMASK_INVALID_INDEX)
+ return -1;
+
+ offset = index * SVGA_QUERY_MEM_BLOCK_SIZE;
+ if (offset >= svga->gb_query_len) {
+ unsigned i;
+
+ /**
+ * All the memory blocks are allocated, lets see if there is
+ * any empty memory block around that can be freed up.
+ */
+ index = -1;
+ for (i = 0; i < SVGA3D_QUERYTYPE_MAX && index == -1; i++) {
+ struct svga_qmem_alloc_entry *alloc_entry;
+ struct svga_qmem_alloc_entry *prev_alloc_entry = NULL;
+
+ alloc_entry = svga->gb_query_map[i];
+ while (alloc_entry && index == -1) {
+ if (alloc_entry->nquery == 0) {
+ /* This memory block is empty, it can be recycled. */
+ if (prev_alloc_entry) {
+ prev_alloc_entry->next = alloc_entry->next;
+ } else {
+ svga->gb_query_map[i] = alloc_entry->next;
+ }
+ index = alloc_entry->block_index;
+ } else {
+ prev_alloc_entry = alloc_entry;
+ alloc_entry = alloc_entry->next;
+ }
+ }
+ }
+ }
+
+ return index;
+}
+
+/**
+ * Allocate a slot in the specified memory block.
+ * All slots in this memory block are of the same size.
+ *
+ * \return -1 if out of memory, else index of the query slot
+ */
+static int
+allocate_query_slot(struct svga_context *svga,
+ struct svga_qmem_alloc_entry *alloc)
+{
+ int index;
+ unsigned offset;
+
+ /* Find the next available slot */
+ index = util_bitmask_add(alloc->alloc_mask);
+
+ if (index == UTIL_BITMASK_INVALID_INDEX)
+ return -1;
+
+ offset = index * alloc->query_size;
+ if (offset >= SVGA_QUERY_MEM_BLOCK_SIZE)
+ return -1;
+
+ alloc->nquery++;
+
+ return index;
+}
+
+/**
+ * Deallocate the specified slot in the memory block.
+ * If all slots are freed up, then deallocate the memory block
+ * as well, so it can be allocated for other query type
+ */
+static void
+deallocate_query_slot(struct svga_context *svga,
+ struct svga_qmem_alloc_entry *alloc,
+ unsigned index)
+{
+ assert(index != UTIL_BITMASK_INVALID_INDEX);
+
+ util_bitmask_clear(alloc->alloc_mask, index);
+ alloc->nquery--;
+
+ /**
+ * Don't worry about deallocating the empty memory block here.
+ * The empty memory block will be recycled when no more memory block
+ * can be allocated.
+ */
+}
+
+static struct svga_qmem_alloc_entry *
+allocate_query_block_entry(struct svga_context *svga,
+ unsigned len)
+{
+ struct svga_qmem_alloc_entry *alloc_entry;
+ int block_index = -1;
+
+ block_index = allocate_query_block(svga);
+ if (block_index == -1)
+ return NULL;
+ alloc_entry = CALLOC_STRUCT(svga_qmem_alloc_entry);
+ if (!alloc_entry)
+ return NULL;
+
+ alloc_entry->block_index = block_index;
+ alloc_entry->start_offset = block_index * SVGA_QUERY_MEM_BLOCK_SIZE;
+ alloc_entry->nquery = 0;
+ alloc_entry->alloc_mask = util_bitmask_create();
+ alloc_entry->next = NULL;
+ alloc_entry->query_size = len;
+
+ return alloc_entry;
+}
+
+/**
+ * Allocate a memory slot for a query of the specified type.
+ * It will first search through the memory blocks that are allocated
+ * for the query type. If no memory slot is available, it will try
+ * to allocate another memory block within the query object memory for
+ * this query type.
+ */
+static int
+allocate_query(struct svga_context *svga,
+ SVGA3dQueryType type,
+ unsigned len)
+{
+ struct svga_qmem_alloc_entry *alloc_entry;
+ int slot_index = -1;
+ unsigned offset;
+
+ assert(type < SVGA3D_QUERYTYPE_MAX);
+
+ alloc_entry = svga->gb_query_map[type];
+
+ if (!alloc_entry) {
+ /**
+ * No query memory block has been allocated for this query type,
+ * allocate one now
+ */
+ alloc_entry = allocate_query_block_entry(svga, len);
+ if (!alloc_entry)
+ return -1;
+ svga->gb_query_map[type] = alloc_entry;
+ }
+
+ /* Allocate a slot within the memory block allocated for this query type */
+ slot_index = allocate_query_slot(svga, alloc_entry);
+
+ if (slot_index == -1) {
+ /* This query memory block is full, allocate another one */
+ alloc_entry = allocate_query_block_entry(svga, len);
+ if (!alloc_entry)
+ return -1;
+ alloc_entry->next = svga->gb_query_map[type];
+ svga->gb_query_map[type] = alloc_entry;
+ slot_index = allocate_query_slot(svga, alloc_entry);
+ }
+
+ assert(slot_index != -1);
+ offset = slot_index * len + alloc_entry->start_offset;
+
+ return offset;
+}
+
+
+/**
+ * Deallocate memory slot allocated for the specified query
+ */
+static void
+deallocate_query(struct svga_context *svga,
+ struct svga_query *sq)
+{
+ struct svga_qmem_alloc_entry *alloc_entry;
+ unsigned slot_index;
+ unsigned offset = sq->offset;
+
+ alloc_entry = svga->gb_query_map[sq->svga_type];
+
+ while (alloc_entry) {
+ if (offset >= alloc_entry->start_offset &&
+ offset < alloc_entry->start_offset + SVGA_QUERY_MEM_BLOCK_SIZE) {
+
+ /* The slot belongs to this memory block, deallocate it */
+ slot_index = (offset - alloc_entry->start_offset) /
+ alloc_entry->query_size;
+ deallocate_query_slot(svga, alloc_entry, slot_index);
+ alloc_entry = NULL;
+ } else {
+ alloc_entry = alloc_entry->next;
+ }
+ }
+}
+
+
+/**
+ * Destroy the gb query object and all the related query structures
+ */
+static void
+destroy_gb_query_obj(struct svga_context *svga)
+{
+ struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+ unsigned i;
+
+ for (i = 0; i < SVGA3D_QUERYTYPE_MAX; i++) {
+ struct svga_qmem_alloc_entry *alloc_entry, *next;
+ alloc_entry = svga->gb_query_map[i];
+ while (alloc_entry) {
+ next = alloc_entry->next;
+ util_bitmask_destroy(alloc_entry->alloc_mask);
+ FREE(alloc_entry);
+ alloc_entry = next;
+ }
+ svga->gb_query_map[i] = NULL;
+ }
+
+ if (svga->gb_query)
+ sws->query_destroy(sws, svga->gb_query);
+ svga->gb_query = NULL;
+
+ util_bitmask_destroy(svga->gb_query_alloc_mask);
+}
+
+/**
+ * Define query and create the gb query object if it is not already created.
+ * There is only one gb query object per context which will be shared by
+ * queries of all types.
+ */
+static enum pipe_error
+define_query_vgpu10(struct svga_context *svga,
+ struct svga_query *sq, int resultLen)
+{
+ struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+ int qlen;
+ enum pipe_error ret = PIPE_OK;
+
+ SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
+
+ if (svga->gb_query == NULL) {
+ /* Create a gb query object */
+ svga->gb_query = sws->query_create(sws, SVGA_QUERY_MEM_SIZE);
+ if (!svga->gb_query)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+ svga->gb_query_len = SVGA_QUERY_MEM_SIZE;
+ memset (svga->gb_query_map, 0, sizeof(svga->gb_query_map));
+ svga->gb_query_alloc_mask = util_bitmask_create();
+
+ /* Bind the query object to the context */
+ if (svga->swc->query_bind(svga->swc, svga->gb_query,
+ SVGA_QUERY_FLAG_SET) != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ svga->swc->query_bind(svga->swc, svga->gb_query,
+ SVGA_QUERY_FLAG_SET);
+ }
+ }
+
+ sq->gb_query = svga->gb_query;
+
+ /* Allocate an integer ID for this query */
+ sq->id = util_bitmask_add(svga->query_id_bm);
+ if (sq->id == UTIL_BITMASK_INVALID_INDEX)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ /* Find a slot for this query in the gb object */
+ qlen = resultLen + sizeof(SVGA3dQueryState);
+ sq->offset = allocate_query(svga, sq->svga_type, qlen);
+ if (sq->offset == -1)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ SVGA_DBG(DEBUG_QUERY, " query type=%d qid=0x%x offset=%d\n",
+ sq->svga_type, sq->id, sq->offset);
+
+ /**
+ * Send SVGA3D commands to define the query
+ */
+ ret = SVGA3D_vgpu10_DefineQuery(svga->swc, sq->id, sq->svga_type, sq->flags);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_vgpu10_DefineQuery(svga->swc, sq->id, sq->svga_type, sq->flags);
+ }
+ if (ret != PIPE_OK)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ ret = SVGA3D_vgpu10_BindQuery(svga->swc, sq->gb_query, sq->id);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_vgpu10_BindQuery(svga->swc, sq->gb_query, sq->id);
+ }
+ assert(ret == PIPE_OK);
+
+ ret = SVGA3D_vgpu10_SetQueryOffset(svga->swc, sq->id, sq->offset);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_vgpu10_SetQueryOffset(svga->swc, sq->id, sq->offset);
+ }
+ assert(ret == PIPE_OK);
+
+ return PIPE_OK;
+}
+
+static enum pipe_error
+destroy_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
+{
+ enum pipe_error ret;
+
+ ret = SVGA3D_vgpu10_DestroyQuery(svga->swc, sq->id);
+
+ /* Deallocate the memory slot allocated for this query */
+ deallocate_query(svga, sq);
+
+ return ret;
+}
+
+
+/**
+ * Rebind queryies to the context.
+ */
+static void
+rebind_vgpu10_query(struct svga_context *svga)
+{
+ if (svga->swc->query_bind(svga->swc, svga->gb_query,
+ SVGA_QUERY_FLAG_REF) != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ svga->swc->query_bind(svga->swc, svga->gb_query,
+ SVGA_QUERY_FLAG_REF);
+ }
+
+ svga->rebind.flags.query = FALSE;
+}
+
+
+static enum pipe_error
+begin_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
+{
+ struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+ enum pipe_error ret = PIPE_OK;
+ int status = 0;
+
+ sws->fence_reference(sws, &sq->fence, NULL);
+
+ /* Initialize the query state to NEW */
+ status = sws->query_init(sws, sq->gb_query, sq->offset, SVGA3D_QUERYSTATE_NEW);
+ if (status)
+ return PIPE_ERROR;
+
+ if (svga->rebind.flags.query) {
+ rebind_vgpu10_query(svga);
+ }
+
+ /* Send the BeginQuery command to the device */
+ ret = SVGA3D_vgpu10_BeginQuery(svga->swc, sq->id);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_vgpu10_BeginQuery(svga->swc, sq->id);
+ }
+ return ret;
+}
+
+static enum pipe_error
+end_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
+{
+ enum pipe_error ret = PIPE_OK;
+
+ if (svga->rebind.flags.query) {
+ rebind_vgpu10_query(svga);
+ }
+
+ ret = SVGA3D_vgpu10_EndQuery(svga->swc, sq->id);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_vgpu10_EndQuery(svga->swc, sq->id);
+ }
+
+ return ret;
+}
+
+static bool
+get_query_result_vgpu10(struct svga_context *svga, struct svga_query *sq,
+ bool wait, void *result, int resultLen)
+{
+ struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
+ SVGA3dQueryState queryState;
+
+ if (svga->rebind.flags.query) {
+ rebind_vgpu10_query(svga);
+ }
+
+ sws->query_get_result(sws, sq->gb_query, sq->offset, &queryState, result, resultLen);
+
+ if (queryState != SVGA3D_QUERYSTATE_SUCCEEDED && !sq->fence) {
+ /* We don't have the query result yet, and the query hasn't been
+ * submitted. We need to submit it now since the GL spec says
+ * "Querying the state for a given occlusion query forces that
+ * occlusion query to complete within a finite amount of time."
+ */
+ svga_context_flush(svga, &sq->fence);
+ }
+
+ if (queryState == SVGA3D_QUERYSTATE_PENDING ||
+ queryState == SVGA3D_QUERYSTATE_NEW) {
+ if (!wait)
+ return false;
+ sws->fence_finish(sws, sq->fence, PIPE_TIMEOUT_INFINITE,
+ SVGA_FENCE_FLAG_QUERY);
+ sws->query_get_result(sws, sq->gb_query, sq->offset, &queryState, result, resultLen);
+ }
+
+ assert(queryState == SVGA3D_QUERYSTATE_SUCCEEDED ||
+ queryState == SVGA3D_QUERYSTATE_FAILED);
+
+ return true;
+}
+
+static struct pipe_query *
+svga_create_query(struct pipe_context *pipe,
+ unsigned query_type,
+ unsigned index)
+{
+ struct svga_context *svga = svga_context(pipe);
+ struct svga_query *sq;
+
+ assert(query_type < SVGA_QUERY_MAX);
+
+ sq = CALLOC_STRUCT(svga_query);
+ if (!sq)
+ goto fail;
+
+ /* Allocate an integer ID for the query */
+ sq->id = util_bitmask_add(svga->query_id_bm);
+ if (sq->id == UTIL_BITMASK_INVALID_INDEX)
+ goto fail;
+
+ SVGA_DBG(DEBUG_QUERY, "%s type=%d sq=0x%x id=%d\n", __FUNCTION__,
+ query_type, sq, sq->id);
+
+ switch (query_type) {
+ case PIPE_QUERY_OCCLUSION_COUNTER:
+ sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSION;
+ if (svga_have_vgpu10(svga)) {
+ define_query_vgpu10(svga, sq, sizeof(SVGADXOcclusionQueryResult));
+
+ /**
+ * In OpenGL, occlusion counter query can be used in conditional
+ * rendering; however, in DX10, only OCCLUSION_PREDICATE query can
+ * be used for predication. Hence, we need to create an occlusion
+ * predicate query along with the occlusion counter query. So when
+ * the occlusion counter query is used for predication, the associated
+ * query of occlusion predicate type will be used
+ * in the SetPredication command.
+ */
+ sq->predicate = svga_create_query(pipe, PIPE_QUERY_OCCLUSION_PREDICATE, index);
+
+ } else {
+ define_query_vgpu9(svga, sq);
+ }
+ break;
+ case PIPE_QUERY_OCCLUSION_PREDICATE:
+ case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
+ if (svga_have_vgpu10(svga)) {
+ sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE;
+ define_query_vgpu10(svga, sq, sizeof(SVGADXOcclusionPredicateQueryResult));
+ } else {
+ sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSION;
+ define_query_vgpu9(svga, sq);
+ }
+ break;
+ case PIPE_QUERY_PRIMITIVES_GENERATED:
+ case PIPE_QUERY_PRIMITIVES_EMITTED:
+ case PIPE_QUERY_SO_STATISTICS:
+ assert(svga_have_vgpu10(svga));
+ sq->svga_type = SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS;
+ define_query_vgpu10(svga, sq,
+ sizeof(SVGADXStreamOutStatisticsQueryResult));
+ break;
+ case PIPE_QUERY_TIMESTAMP:
+ assert(svga_have_vgpu10(svga));
+ sq->svga_type = SVGA3D_QUERYTYPE_TIMESTAMP;
+ define_query_vgpu10(svga, sq,
+ sizeof(SVGADXTimestampQueryResult));
+ break;
+ case SVGA_QUERY_NUM_DRAW_CALLS:
+ case SVGA_QUERY_NUM_FALLBACKS:
+ case SVGA_QUERY_NUM_FLUSHES:
+ case SVGA_QUERY_NUM_VALIDATIONS:
+ case SVGA_QUERY_NUM_BUFFERS_MAPPED:
+ case SVGA_QUERY_NUM_TEXTURES_MAPPED:
+ case SVGA_QUERY_NUM_BYTES_UPLOADED:
+ case SVGA_QUERY_COMMAND_BUFFER_SIZE:
+ case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
+ case SVGA_QUERY_MEMORY_USED:
+ case SVGA_QUERY_NUM_SHADERS:
+ case SVGA_QUERY_NUM_RESOURCES:
+ case SVGA_QUERY_NUM_STATE_OBJECTS:
+ case SVGA_QUERY_NUM_SURFACE_VIEWS:
+ case SVGA_QUERY_NUM_GENERATE_MIPMAP:
+ case SVGA_QUERY_NUM_READBACKS:
+ case SVGA_QUERY_NUM_RESOURCE_UPDATES:
+ case SVGA_QUERY_NUM_BUFFER_UPLOADS:
+ case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
+ case SVGA_QUERY_NUM_CONST_UPDATES:
+ case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
+ case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
+ break;
+ case SVGA_QUERY_FLUSH_TIME:
+ case SVGA_QUERY_MAP_BUFFER_TIME:
+ /* These queries need os_time_get() */
+ svga->hud.uses_time = TRUE;
+ break;
+ default:
+ assert(!"unexpected query type in svga_create_query()");
+ }
+
+ sq->type = query_type;
+