1/**********************************************************
2 * Copyright 2008-2015 VMware, Inc.  All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26#include "pipe/p_state.h"
27#include "pipe/p_context.h"
28
29#include "util/u_bitmask.h"
30#include "util/u_memory.h"
31
32#include "svga_cmd.h"
33#include "svga_context.h"
34#include "svga_screen.h"
35#include "svga_resource_buffer.h"
36#include "svga_winsys.h"
37#include "svga_debug.h"
38
39
40/* Fixme: want a public base class for all pipe structs, even if there
41 * isn't much in them.
42 */
43struct pipe_query {
44   int dummy;
45};
46
47struct svga_query {
48   struct pipe_query base;
49   unsigned type;                  /**< PIPE_QUERY_x or SVGA_QUERY_x */
50   SVGA3dQueryType svga_type;      /**< SVGA3D_QUERYTYPE_x or unused */
51
52   unsigned id;                    /** Per-context query identifier */
53   boolean active;                 /** TRUE if query is active */
54
55   struct pipe_fence_handle *fence;
56
57   /** For PIPE_QUERY_OCCLUSION_COUNTER / SVGA3D_QUERYTYPE_OCCLUSION */
58
59   /* For VGPU9 */
60   struct svga_winsys_buffer *hwbuf;
61   volatile SVGA3dQueryResult *queryResult;
62
63   /** For VGPU10 */
64   struct svga_winsys_gb_query *gb_query;
65   SVGA3dDXQueryFlags flags;
66   unsigned offset;                /**< offset to the gb_query memory */
67   struct pipe_query *predicate;   /** The associated query that can be used for predicate */
68
69   /** For non-GPU SVGA_QUERY_x queries */
70   uint64_t begin_count, end_count;
71};
72
73
74/** cast wrapper */
75static inline struct svga_query *
76svga_query(struct pipe_query *q)
77{
78   return (struct svga_query *)q;
79}
80
81/**
82 * VGPU9
83 */
84
85static bool
86svga_get_query_result(struct pipe_context *pipe,
87                      struct pipe_query *q,
88                      bool wait,
89                      union pipe_query_result *result);
90
91static enum pipe_error
92define_query_vgpu9(struct svga_context *svga,
93                   struct svga_query *sq)
94{
95   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
96
97   sq->hwbuf = svga_winsys_buffer_create(svga, 1,
98                                         SVGA_BUFFER_USAGE_PINNED,
99                                         sizeof *sq->queryResult);
100   if (!sq->hwbuf)
101      return PIPE_ERROR_OUT_OF_MEMORY;
102
103   sq->queryResult = (SVGA3dQueryResult *)
104                     sws->buffer_map(sws, sq->hwbuf, PIPE_MAP_WRITE);
105   if (!sq->queryResult) {
106      sws->buffer_destroy(sws, sq->hwbuf);
107      return PIPE_ERROR_OUT_OF_MEMORY;
108   }
109
110   sq->queryResult->totalSize = sizeof *sq->queryResult;
111   sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
112
113   /* We request the buffer to be pinned and assume it is always mapped.
114    * The reason is that we don't want to wait for fences when checking the
115    * query status.
116    */
117   sws->buffer_unmap(sws, sq->hwbuf);
118
119   return PIPE_OK;
120}
121
122static void
123begin_query_vgpu9(struct svga_context *svga, struct svga_query *sq)
124{
125   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
126
127   if (sq->queryResult->state == SVGA3D_QUERYSTATE_PENDING) {
128      /* The application doesn't care for the pending query result.
129       * We cannot let go of the existing buffer and just get a new one
130       * because its storage may be reused for other purposes and clobbered
131       * by the host when it determines the query result.  So the only
132       * option here is to wait for the existing query's result -- not a
133       * big deal, given that no sane application would do this.
134       */
135       uint64_t result;
136       svga_get_query_result(&svga->pipe, &sq->base, TRUE, (void*)&result);
137       assert(sq->queryResult->state != SVGA3D_QUERYSTATE_PENDING);
138   }
139
140   sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
141   sws->fence_reference(sws, &sq->fence, NULL);
142
143   SVGA_RETRY(svga, SVGA3D_BeginQuery(svga->swc, sq->svga_type));
144}
145
146static void
147end_query_vgpu9(struct svga_context *svga, struct svga_query *sq)
148{
149   /* Set to PENDING before sending EndQuery. */
150   sq->queryResult->state = SVGA3D_QUERYSTATE_PENDING;
151
152   SVGA_RETRY(svga, SVGA3D_EndQuery(svga->swc, sq->svga_type, sq->hwbuf));
153}
154
155static bool
156get_query_result_vgpu9(struct svga_context *svga, struct svga_query *sq,
157                       bool wait, uint64_t *result)
158{
159   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
160   SVGA3dQueryState state;
161
162   if (!sq->fence) {
163      /* The query status won't be updated by the host unless
164       * SVGA_3D_CMD_WAIT_FOR_QUERY is emitted. Unfortunately this will cause
165       * a synchronous wait on the host.
166       */
167      SVGA_RETRY(svga, SVGA3D_WaitForQuery(svga->swc, sq->svga_type,
168                                           sq->hwbuf));
169      svga_context_flush(svga, &sq->fence);
170      assert(sq->fence);
171   }
172
173   state = sq->queryResult->state;
174   if (state == SVGA3D_QUERYSTATE_PENDING) {
175      if (!wait)
176         return false;
177      sws->fence_finish(sws, sq->fence, PIPE_TIMEOUT_INFINITE,
178                        SVGA_FENCE_FLAG_QUERY);
179      state = sq->queryResult->state;
180   }
181
182   assert(state == SVGA3D_QUERYSTATE_SUCCEEDED ||
183          state == SVGA3D_QUERYSTATE_FAILED);
184
185   *result = (uint64_t)sq->queryResult->result32;
186   return true;
187}
188
189
190/**
191 * VGPU10
192 *
193 * There is one query mob allocated for each context to be shared by all
194 * query types. The mob is used to hold queries's state and result. Since
195 * each query result type is of different length, to ease the query allocation
196 * management, the mob is divided into memory blocks. Each memory block
197 * will hold queries of the same type. Multiple memory blocks can be allocated
198 * for a particular query type.
199 *
200 * Currently each memory block is of 184 bytes. We support up to 512
201 * memory blocks. The query memory size is arbitrary right now.
202 * Each occlusion query takes about 8 bytes. One memory block can accomodate
203 * 23 occlusion queries. 512 of those blocks can support up to 11K occlusion
204 * queries. That seems reasonable for now. If we think this limit is
205 * not enough, we can increase the limit or try to grow the mob in runtime.
206 * Note, SVGA device does not impose one mob per context for queries,
207 * we could allocate multiple mobs for queries; however, wddm KMD does not
208 * currently support that.
209 *
210 * Also note that the GL guest driver does not issue any of the
211 * following commands: DXMoveQuery, DXBindAllQuery & DXReadbackAllQuery.
212 */
213#define SVGA_QUERY_MEM_BLOCK_SIZE    (sizeof(SVGADXQueryResultUnion) * 2)
214#define SVGA_QUERY_MEM_SIZE          (512 * SVGA_QUERY_MEM_BLOCK_SIZE)
215
216struct svga_qmem_alloc_entry
217{
218   unsigned start_offset;               /* start offset of the memory block */
219   unsigned block_index;                /* block index of the memory block */
220   unsigned query_size;                 /* query size in this memory block */
221   unsigned nquery;                     /* number of queries allocated */
222   struct util_bitmask *alloc_mask;     /* allocation mask */
223   struct svga_qmem_alloc_entry *next;  /* next memory block */
224};
225
226
227/**
228 * Allocate a memory block from the query object memory
229 * \return NULL if out of memory, else pointer to the query memory block
230 */
231static struct svga_qmem_alloc_entry *
232allocate_query_block(struct svga_context *svga)
233{
234   int index;
235   unsigned offset;
236   struct svga_qmem_alloc_entry *alloc_entry = NULL;
237
238   /* Find the next available query block */
239   index = util_bitmask_add(svga->gb_query_alloc_mask);
240
241   if (index == UTIL_BITMASK_INVALID_INDEX)
242      return NULL;
243
244   offset = index * SVGA_QUERY_MEM_BLOCK_SIZE;
245   if (offset >= svga->gb_query_len) {
246      unsigned i;
247
248      /* Deallocate the out-of-range index */
249      util_bitmask_clear(svga->gb_query_alloc_mask, index);
250      index = -1;
251
252      /**
253       * All the memory blocks are allocated, lets see if there is
254       * any empty memory block around that can be freed up.
255       */
256      for (i = 0; i < SVGA3D_QUERYTYPE_MAX && index == -1; i++) {
257         struct svga_qmem_alloc_entry *prev_alloc_entry = NULL;
258
259         alloc_entry = svga->gb_query_map[i];
260         while (alloc_entry && index == -1) {
261            if (alloc_entry->nquery == 0) {
262               /* This memory block is empty, it can be recycled. */
263               if (prev_alloc_entry) {
264                  prev_alloc_entry->next = alloc_entry->next;
265               } else {
266                  svga->gb_query_map[i] = alloc_entry->next;
267               }
268               index = alloc_entry->block_index;
269            } else {
270               prev_alloc_entry = alloc_entry;
271               alloc_entry = alloc_entry->next;
272            }
273         }
274      }
275
276      if (index == -1) {
277         debug_printf("Query memory object is full\n");
278         return NULL;
279      }
280   }
281
282   if (!alloc_entry) {
283      assert(index != -1);
284      alloc_entry = CALLOC_STRUCT(svga_qmem_alloc_entry);
285      alloc_entry->block_index = index;
286   }
287
288   return alloc_entry;
289}
290
291/**
292 * Allocate a slot in the specified memory block.
293 * All slots in this memory block are of the same size.
294 *
295 * \return -1 if out of memory, else index of the query slot
296 */
297static int
298allocate_query_slot(struct svga_context *svga,
299                    struct svga_qmem_alloc_entry *alloc)
300{
301   int index;
302   unsigned offset;
303
304   /* Find the next available slot */
305   index = util_bitmask_add(alloc->alloc_mask);
306
307   if (index == UTIL_BITMASK_INVALID_INDEX)
308      return -1;
309
310   offset = index * alloc->query_size;
311   if (offset >= SVGA_QUERY_MEM_BLOCK_SIZE)
312      return -1;
313
314   alloc->nquery++;
315
316   return index;
317}
318
319/**
320 * Deallocate the specified slot in the memory block.
321 * If all slots are freed up, then deallocate the memory block
322 * as well, so it can be allocated for other query type
323 */
324static void
325deallocate_query_slot(struct svga_context *svga,
326                      struct svga_qmem_alloc_entry *alloc,
327                      unsigned index)
328{
329   assert(index != UTIL_BITMASK_INVALID_INDEX);
330
331   util_bitmask_clear(alloc->alloc_mask, index);
332   alloc->nquery--;
333
334   /**
335    * Don't worry about deallocating the empty memory block here.
336    * The empty memory block will be recycled when no more memory block
337    * can be allocated.
338    */
339}
340
341static struct svga_qmem_alloc_entry *
342allocate_query_block_entry(struct svga_context *svga,
343                           unsigned len)
344{
345   struct svga_qmem_alloc_entry *alloc_entry;
346
347   alloc_entry = allocate_query_block(svga);
348   if (!alloc_entry)
349      return NULL;
350
351   assert(alloc_entry->block_index != -1);
352   alloc_entry->start_offset =
353      alloc_entry->block_index * SVGA_QUERY_MEM_BLOCK_SIZE;
354   alloc_entry->nquery = 0;
355   alloc_entry->alloc_mask = util_bitmask_create();
356   alloc_entry->next = NULL;
357   alloc_entry->query_size = len;
358
359   return alloc_entry;
360}
361
362/**
363 * Allocate a memory slot for a query of the specified type.
364 * It will first search through the memory blocks that are allocated
365 * for the query type. If no memory slot is available, it will try
366 * to allocate another memory block within the query object memory for
367 * this query type.
368 */
369static int
370allocate_query(struct svga_context *svga,
371               SVGA3dQueryType type,
372               unsigned len)
373{
374   struct svga_qmem_alloc_entry *alloc_entry;
375   int slot_index = -1;
376   unsigned offset;
377
378   assert(type < SVGA3D_QUERYTYPE_MAX);
379
380   alloc_entry = svga->gb_query_map[type];
381
382   if (!alloc_entry) {
383      /**
384       * No query memory block has been allocated for this query type,
385       * allocate one now
386       */
387      alloc_entry = allocate_query_block_entry(svga, len);
388      if (!alloc_entry)
389         return -1;
390      svga->gb_query_map[type] = alloc_entry;
391   }
392
393   /* Allocate a slot within the memory block allocated for this query type */
394   slot_index = allocate_query_slot(svga, alloc_entry);
395
396   if (slot_index == -1) {
397      /* This query memory block is full, allocate another one */
398      alloc_entry = allocate_query_block_entry(svga, len);
399      if (!alloc_entry)
400         return -1;
401      alloc_entry->next = svga->gb_query_map[type];
402      svga->gb_query_map[type] = alloc_entry;
403      slot_index = allocate_query_slot(svga, alloc_entry);
404   }
405
406   assert(slot_index != -1);
407   offset = slot_index * len + alloc_entry->start_offset;
408
409   return offset;
410}
411
412
413/**
414 * Deallocate memory slot allocated for the specified query
415 */
416static void
417deallocate_query(struct svga_context *svga,
418                 struct svga_query *sq)
419{
420   struct svga_qmem_alloc_entry *alloc_entry;
421   unsigned slot_index;
422   unsigned offset = sq->offset;
423
424   alloc_entry = svga->gb_query_map[sq->svga_type];
425
426   while (alloc_entry) {
427      if (offset >= alloc_entry->start_offset &&
428          offset < alloc_entry->start_offset + SVGA_QUERY_MEM_BLOCK_SIZE) {
429
430         /* The slot belongs to this memory block, deallocate it */
431         slot_index = (offset - alloc_entry->start_offset) /
432                      alloc_entry->query_size;
433         deallocate_query_slot(svga, alloc_entry, slot_index);
434         alloc_entry = NULL;
435      } else {
436         alloc_entry = alloc_entry->next;
437      }
438   }
439}
440
441
442/**
443 * Destroy the gb query object and all the related query structures
444 */
445static void
446destroy_gb_query_obj(struct svga_context *svga)
447{
448   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
449   unsigned i;
450
451   for (i = 0; i < SVGA3D_QUERYTYPE_MAX; i++) {
452      struct svga_qmem_alloc_entry *alloc_entry, *next;
453      alloc_entry = svga->gb_query_map[i];
454      while (alloc_entry) {
455         next = alloc_entry->next;
456         util_bitmask_destroy(alloc_entry->alloc_mask);
457         FREE(alloc_entry);
458         alloc_entry = next;
459      }
460      svga->gb_query_map[i] = NULL;
461   }
462
463   if (svga->gb_query)
464      sws->query_destroy(sws, svga->gb_query);
465   svga->gb_query = NULL;
466
467   util_bitmask_destroy(svga->gb_query_alloc_mask);
468}
469
470/**
471 * Define query and create the gb query object if it is not already created.
472 * There is only one gb query object per context which will be shared by
473 * queries of all types.
474 */
475static enum pipe_error
476define_query_vgpu10(struct svga_context *svga,
477                    struct svga_query *sq, int resultLen)
478{
479   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
480   int qlen;
481   enum pipe_error ret = PIPE_OK;
482
483   SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
484
485   if (svga->gb_query == NULL) {
486      /* Create a gb query object */
487      svga->gb_query = sws->query_create(sws, SVGA_QUERY_MEM_SIZE);
488      if (!svga->gb_query)
489         return PIPE_ERROR_OUT_OF_MEMORY;
490      svga->gb_query_len = SVGA_QUERY_MEM_SIZE;
491      memset (svga->gb_query_map, 0, sizeof(svga->gb_query_map));
492      svga->gb_query_alloc_mask = util_bitmask_create();
493
494      /* Bind the query object to the context */
495      SVGA_RETRY(svga, svga->swc->query_bind(svga->swc, svga->gb_query,
496                                             SVGA_QUERY_FLAG_SET));
497   }
498
499   sq->gb_query = svga->gb_query;
500
501   /* Make sure query length is in multiples of 8 bytes */
502   qlen = align(resultLen + sizeof(SVGA3dQueryState), 8);
503
504   /* Find a slot for this query in the gb object */
505   sq->offset = allocate_query(svga, sq->svga_type, qlen);
506   if (sq->offset == -1)
507      return PIPE_ERROR_OUT_OF_MEMORY;
508
509   assert((sq->offset & 7) == 0);
510
511   SVGA_DBG(DEBUG_QUERY, "   query type=%d qid=0x%x offset=%d\n",
512            sq->svga_type, sq->id, sq->offset);
513
514   /**
515    * Send SVGA3D commands to define the query
516    */
517   SVGA_RETRY_OOM(svga, ret, SVGA3D_vgpu10_DefineQuery(svga->swc, sq->id,
518                                                       sq->svga_type,
519                                                       sq->flags));
520   if (ret != PIPE_OK)
521      return PIPE_ERROR_OUT_OF_MEMORY;
522
523   SVGA_RETRY(svga, SVGA3D_vgpu10_BindQuery(svga->swc, sq->gb_query, sq->id));
524   SVGA_RETRY(svga, SVGA3D_vgpu10_SetQueryOffset(svga->swc, sq->id,
525                                                 sq->offset));
526
527   return PIPE_OK;
528}
529
530static void
531destroy_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
532{
533   SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyQuery(svga->swc, sq->id));
534
535   /* Deallocate the memory slot allocated for this query */
536   deallocate_query(svga, sq);
537}
538
539
540/**
541 * Rebind queryies to the context.
542 */
543static void
544rebind_vgpu10_query(struct svga_context *svga)
545{
546   SVGA_RETRY(svga, svga->swc->query_bind(svga->swc, svga->gb_query,
547                                          SVGA_QUERY_FLAG_REF));
548   svga->rebind.flags.query = FALSE;
549}
550
551
552static enum pipe_error
553begin_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
554{
555   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
556   int status = 0;
557
558   sws->fence_reference(sws, &sq->fence, NULL);
559
560   /* Initialize the query state to NEW */
561   status = sws->query_init(sws, sq->gb_query, sq->offset, SVGA3D_QUERYSTATE_NEW);
562   if (status)
563      return PIPE_ERROR;
564
565   if (svga->rebind.flags.query) {
566      rebind_vgpu10_query(svga);
567   }
568
569   /* Send the BeginQuery command to the device */
570   SVGA_RETRY(svga, SVGA3D_vgpu10_BeginQuery(svga->swc, sq->id));
571   return PIPE_OK;
572}
573
574static void
575end_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
576{
577   if (svga->rebind.flags.query) {
578      rebind_vgpu10_query(svga);
579   }
580
581   SVGA_RETRY(svga, SVGA3D_vgpu10_EndQuery(svga->swc, sq->id));
582}
583
584static bool
585get_query_result_vgpu10(struct svga_context *svga, struct svga_query *sq,
586                        bool wait, void *result, int resultLen)
587{
588   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
589   SVGA3dQueryState queryState;
590
591   if (svga->rebind.flags.query) {
592      rebind_vgpu10_query(svga);
593   }
594
595   sws->query_get_result(sws, sq->gb_query, sq->offset, &queryState, result, resultLen);
596
597   if (queryState != SVGA3D_QUERYSTATE_SUCCEEDED && !sq->fence) {
598      /* We don't have the query result yet, and the query hasn't been
599       * submitted.  We need to submit it now since the GL spec says
600       * "Querying the state for a given occlusion query forces that
601       * occlusion query to complete within a finite amount of time."
602       */
603      svga_context_flush(svga, &sq->fence);
604   }
605
606   if (queryState == SVGA3D_QUERYSTATE_PENDING ||
607       queryState == SVGA3D_QUERYSTATE_NEW) {
608      if (!wait)
609         return false;
610      sws->fence_finish(sws, sq->fence, PIPE_TIMEOUT_INFINITE,
611                        SVGA_FENCE_FLAG_QUERY);
612      sws->query_get_result(sws, sq->gb_query, sq->offset, &queryState, result, resultLen);
613   }
614
615   assert(queryState == SVGA3D_QUERYSTATE_SUCCEEDED ||
616          queryState == SVGA3D_QUERYSTATE_FAILED);
617
618   return true;
619}
620
621static struct pipe_query *
622svga_create_query(struct pipe_context *pipe,
623                  unsigned query_type,
624                  unsigned index)
625{
626   struct svga_context *svga = svga_context(pipe);
627   struct svga_query *sq;
628   enum pipe_error ret;
629
630   assert(query_type < SVGA_QUERY_MAX);
631
632   sq = CALLOC_STRUCT(svga_query);
633   if (!sq)
634      goto fail;
635
636   /* Allocate an integer ID for the query */
637   sq->id = util_bitmask_add(svga->query_id_bm);
638   if (sq->id == UTIL_BITMASK_INVALID_INDEX)
639      goto fail;
640
641   SVGA_DBG(DEBUG_QUERY, "%s type=%d sq=0x%x id=%d\n", __FUNCTION__,
642            query_type, sq, sq->id);
643
644   switch (query_type) {
645   case PIPE_QUERY_OCCLUSION_COUNTER:
646      sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSION;
647      if (svga_have_vgpu10(svga)) {
648         ret = define_query_vgpu10(svga, sq,
649                                   sizeof(SVGADXOcclusionQueryResult));
650         if (ret != PIPE_OK)
651            goto fail;
652
653         /**
654          * In OpenGL, occlusion counter query can be used in conditional
655          * rendering; however, in DX10, only OCCLUSION_PREDICATE query can
656          * be used for predication. Hence, we need to create an occlusion
657          * predicate query along with the occlusion counter query. So when
658          * the occlusion counter query is used for predication, the associated
659          * query of occlusion predicate type will be used
660          * in the SetPredication command.
661          */
662         sq->predicate = svga_create_query(pipe, PIPE_QUERY_OCCLUSION_PREDICATE, index);
663
664      } else {
665         ret = define_query_vgpu9(svga, sq);
666         if (ret != PIPE_OK)
667            goto fail;
668      }
669      break;
670   case PIPE_QUERY_OCCLUSION_PREDICATE:
671   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
672      if (svga_have_vgpu10(svga)) {
673         sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE;
674         ret = define_query_vgpu10(svga, sq,
675                                   sizeof(SVGADXOcclusionPredicateQueryResult));
676         if (ret != PIPE_OK)
677            goto fail;
678      } else {
679         sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSION;
680         ret = define_query_vgpu9(svga, sq);
681         if (ret != PIPE_OK)
682            goto fail;
683      }
684      break;
685   case PIPE_QUERY_PRIMITIVES_GENERATED:
686   case PIPE_QUERY_PRIMITIVES_EMITTED:
687   case PIPE_QUERY_SO_STATISTICS:
688      assert(svga_have_vgpu10(svga));
689
690      /* Until the device supports the new query type for multiple streams,
691       * we will use the single stream query type for stream 0.
692       */
693      if (svga_have_sm5(svga) && index > 0) {
694         assert(index < 4);
695
696         sq->svga_type = SVGA3D_QUERYTYPE_SOSTATS_STREAM0 + index;
697      }
698      else {
699         assert(index == 0);
700         sq->svga_type = SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS;
701      }
702      ret = define_query_vgpu10(svga, sq,
703                                sizeof(SVGADXStreamOutStatisticsQueryResult));
704      if (ret != PIPE_OK)
705         goto fail;
706      break;
707   case PIPE_QUERY_TIMESTAMP:
708      assert(svga_have_vgpu10(svga));
709      sq->svga_type = SVGA3D_QUERYTYPE_TIMESTAMP;
710      ret = define_query_vgpu10(svga, sq,
711                                sizeof(SVGADXTimestampQueryResult));
712      if (ret != PIPE_OK)
713         goto fail;
714      break;
715   case SVGA_QUERY_NUM_DRAW_CALLS:
716   case SVGA_QUERY_NUM_FALLBACKS:
717   case SVGA_QUERY_NUM_FLUSHES:
718   case SVGA_QUERY_NUM_VALIDATIONS:
719   case SVGA_QUERY_NUM_BUFFERS_MAPPED:
720   case SVGA_QUERY_NUM_TEXTURES_MAPPED:
721   case SVGA_QUERY_NUM_BYTES_UPLOADED:
722   case SVGA_QUERY_NUM_COMMAND_BUFFERS:
723   case SVGA_QUERY_COMMAND_BUFFER_SIZE:
724   case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
725   case SVGA_QUERY_MEMORY_USED:
726   case SVGA_QUERY_NUM_SHADERS:
727   case SVGA_QUERY_NUM_RESOURCES:
728   case SVGA_QUERY_NUM_STATE_OBJECTS:
729   case SVGA_QUERY_NUM_SURFACE_VIEWS:
730   case SVGA_QUERY_NUM_GENERATE_MIPMAP:
731   case SVGA_QUERY_NUM_READBACKS:
732   case SVGA_QUERY_NUM_RESOURCE_UPDATES:
733   case SVGA_QUERY_NUM_BUFFER_UPLOADS:
734   case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
735   case SVGA_QUERY_NUM_CONST_UPDATES:
736   case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
737   case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
738   case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
739   case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
740   case SVGA_QUERY_SHADER_MEM_USED:
741      break;
742   case SVGA_QUERY_FLUSH_TIME:
743   case SVGA_QUERY_MAP_BUFFER_TIME:
744      /* These queries need os_time_get() */
745      svga->hud.uses_time = TRUE;
746      break;
747
748   default:
749      assert(!"unexpected query type in svga_create_query()");
750   }
751
752   sq->type = query_type;
753
754   return &sq->base;
755
756fail:
757   FREE(sq);
758   return NULL;
759}
760
761static void
762svga_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
763{
764   struct svga_context *svga = svga_context(pipe);
765   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
766   struct svga_query *sq;
767
768   if (!q) {
769      destroy_gb_query_obj(svga);
770      return;
771   }
772
773   sq = svga_query(q);
774
775   SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d\n", __FUNCTION__,
776            sq, sq->id);
777
778   switch (sq->type) {
779   case PIPE_QUERY_OCCLUSION_COUNTER:
780   case PIPE_QUERY_OCCLUSION_PREDICATE:
781   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
782      if (svga_have_vgpu10(svga)) {
783         /* make sure to also destroy any associated predicate query */
784         if (sq->predicate)
785            svga_destroy_query(pipe, sq->predicate);
786         destroy_query_vgpu10(svga, sq);
787      } else {
788         sws->buffer_destroy(sws, sq->hwbuf);
789      }
790      sws->fence_reference(sws, &sq->fence, NULL);
791      break;
792   case PIPE_QUERY_PRIMITIVES_GENERATED:
793   case PIPE_QUERY_PRIMITIVES_EMITTED:
794   case PIPE_QUERY_SO_STATISTICS:
795   case PIPE_QUERY_TIMESTAMP:
796      assert(svga_have_vgpu10(svga));
797      destroy_query_vgpu10(svga, sq);
798      sws->fence_reference(sws, &sq->fence, NULL);
799      break;
800   case SVGA_QUERY_NUM_DRAW_CALLS:
801   case SVGA_QUERY_NUM_FALLBACKS:
802   case SVGA_QUERY_NUM_FLUSHES:
803   case SVGA_QUERY_NUM_VALIDATIONS:
804   case SVGA_QUERY_MAP_BUFFER_TIME:
805   case SVGA_QUERY_NUM_BUFFERS_MAPPED:
806   case SVGA_QUERY_NUM_TEXTURES_MAPPED:
807   case SVGA_QUERY_NUM_BYTES_UPLOADED:
808   case SVGA_QUERY_NUM_COMMAND_BUFFERS:
809   case SVGA_QUERY_COMMAND_BUFFER_SIZE:
810   case SVGA_QUERY_FLUSH_TIME:
811   case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
812   case SVGA_QUERY_MEMORY_USED:
813   case SVGA_QUERY_NUM_SHADERS:
814   case SVGA_QUERY_NUM_RESOURCES:
815   case SVGA_QUERY_NUM_STATE_OBJECTS:
816   case SVGA_QUERY_NUM_SURFACE_VIEWS:
817   case SVGA_QUERY_NUM_GENERATE_MIPMAP:
818   case SVGA_QUERY_NUM_READBACKS:
819   case SVGA_QUERY_NUM_RESOURCE_UPDATES:
820   case SVGA_QUERY_NUM_BUFFER_UPLOADS:
821   case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
822   case SVGA_QUERY_NUM_CONST_UPDATES:
823   case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
824   case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
825   case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
826   case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
827   case SVGA_QUERY_SHADER_MEM_USED:
828      /* nothing */
829      break;
830   default:
831      assert(!"svga: unexpected query type in svga_destroy_query()");
832   }
833
834   /* Free the query id */
835   util_bitmask_clear(svga->query_id_bm, sq->id);
836
837   FREE(sq);
838}
839
840
841static bool
842svga_begin_query(struct pipe_context *pipe, struct pipe_query *q)
843{
844   struct svga_context *svga = svga_context(pipe);
845   struct svga_query *sq = svga_query(q);
846   enum pipe_error ret = PIPE_OK;
847
848   assert(sq);
849   assert(sq->type < SVGA_QUERY_MAX);
850
851   /* Need to flush out buffered drawing commands so that they don't
852    * get counted in the query results.
853    */
854   svga_hwtnl_flush_retry(svga);
855
856   switch (sq->type) {
857   case PIPE_QUERY_OCCLUSION_COUNTER:
858   case PIPE_QUERY_OCCLUSION_PREDICATE:
859   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
860      if (svga_have_vgpu10(svga)) {
861         ret = begin_query_vgpu10(svga, sq);
862         /* also need to start the associated occlusion predicate query */
863         if (sq->predicate) {
864            enum pipe_error status;
865            status = begin_query_vgpu10(svga, svga_query(sq->predicate));
866            assert(status == PIPE_OK);
867            (void) status;
868         }
869      } else {
870         begin_query_vgpu9(svga, sq);
871      }
872      assert(ret == PIPE_OK);
873      (void) ret;
874      break;
875   case PIPE_QUERY_PRIMITIVES_GENERATED:
876   case PIPE_QUERY_PRIMITIVES_EMITTED:
877   case PIPE_QUERY_SO_STATISTICS:
878   case PIPE_QUERY_TIMESTAMP:
879      assert(svga_have_vgpu10(svga));
880      ret = begin_query_vgpu10(svga, sq);
881      assert(ret == PIPE_OK);
882      break;
883   case SVGA_QUERY_NUM_DRAW_CALLS:
884      sq->begin_count = svga->hud.num_draw_calls;
885      break;
886   case SVGA_QUERY_NUM_FALLBACKS:
887      sq->begin_count = svga->hud.num_fallbacks;
888      break;
889   case SVGA_QUERY_NUM_FLUSHES:
890      sq->begin_count = svga->hud.num_flushes;
891      break;
892   case SVGA_QUERY_NUM_VALIDATIONS:
893      sq->begin_count = svga->hud.num_validations;
894      break;
895   case SVGA_QUERY_MAP_BUFFER_TIME:
896      sq->begin_count = svga->hud.map_buffer_time;
897      break;
898   case SVGA_QUERY_NUM_BUFFERS_MAPPED:
899      sq->begin_count = svga->hud.num_buffers_mapped;
900      break;
901   case SVGA_QUERY_NUM_TEXTURES_MAPPED:
902      sq->begin_count = svga->hud.num_textures_mapped;
903      break;
904   case SVGA_QUERY_NUM_BYTES_UPLOADED:
905      sq->begin_count = svga->hud.num_bytes_uploaded;
906      break;
907   case SVGA_QUERY_NUM_COMMAND_BUFFERS:
908      sq->begin_count = svga->swc->num_command_buffers;
909      break;
910   case SVGA_QUERY_COMMAND_BUFFER_SIZE:
911      sq->begin_count = svga->hud.command_buffer_size;
912      break;
913   case SVGA_QUERY_FLUSH_TIME:
914      sq->begin_count = svga->hud.flush_time;
915      break;
916   case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
917      sq->begin_count = svga->hud.surface_write_flushes;
918      break;
919   case SVGA_QUERY_NUM_READBACKS:
920      sq->begin_count = svga->hud.num_readbacks;
921      break;
922   case SVGA_QUERY_NUM_RESOURCE_UPDATES:
923      sq->begin_count = svga->hud.num_resource_updates;
924      break;
925   case SVGA_QUERY_NUM_BUFFER_UPLOADS:
926      sq->begin_count = svga->hud.num_buffer_uploads;
927      break;
928   case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
929      sq->begin_count = svga->hud.num_const_buf_updates;
930      break;
931   case SVGA_QUERY_NUM_CONST_UPDATES:
932      sq->begin_count = svga->hud.num_const_updates;
933      break;
934   case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
935      sq->begin_count = svga->swc->num_shader_reloc;
936      break;
937   case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
938      sq->begin_count = svga->swc->num_surf_reloc;
939      break;
940   case SVGA_QUERY_MEMORY_USED:
941   case SVGA_QUERY_NUM_SHADERS:
942   case SVGA_QUERY_NUM_RESOURCES:
943   case SVGA_QUERY_NUM_STATE_OBJECTS:
944   case SVGA_QUERY_NUM_SURFACE_VIEWS:
945   case SVGA_QUERY_NUM_GENERATE_MIPMAP:
946   case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
947   case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
948   case SVGA_QUERY_SHADER_MEM_USED:
949      /* nothing */
950      break;
951   default:
952      assert(!"unexpected query type in svga_begin_query()");
953   }
954
955   SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d type=%d svga_type=%d\n",
956            __FUNCTION__, sq, sq->id, sq->type, sq->svga_type);
957
958   sq->active = TRUE;
959
960   return true;
961}
962
963
964static bool
965svga_end_query(struct pipe_context *pipe, struct pipe_query *q)
966{
967   struct svga_context *svga = svga_context(pipe);
968   struct svga_query *sq = svga_query(q);
969
970   assert(sq);
971   assert(sq->type < SVGA_QUERY_MAX);
972
973   SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x type=%d\n",
974            __FUNCTION__, sq, sq->type);
975
976   if (sq->type == PIPE_QUERY_TIMESTAMP && !sq->active)
977      svga_begin_query(pipe, q);
978
979   SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d type=%d svga_type=%d\n",
980            __FUNCTION__, sq, sq->id, sq->type, sq->svga_type);
981
982   svga_hwtnl_flush_retry(svga);
983
984   assert(sq->active);
985
986   switch (sq->type) {
987   case PIPE_QUERY_OCCLUSION_COUNTER:
988   case PIPE_QUERY_OCCLUSION_PREDICATE:
989   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
990      if (svga_have_vgpu10(svga)) {
991         end_query_vgpu10(svga, sq);
992         /* also need to end the associated occlusion predicate query */
993         if (sq->predicate) {
994            end_query_vgpu10(svga, svga_query(sq->predicate));
995         }
996      } else {
997         end_query_vgpu9(svga, sq);
998      }
999      break;
1000   case PIPE_QUERY_PRIMITIVES_GENERATED:
1001   case PIPE_QUERY_PRIMITIVES_EMITTED:
1002   case PIPE_QUERY_SO_STATISTICS:
1003   case PIPE_QUERY_TIMESTAMP:
1004      assert(svga_have_vgpu10(svga));
1005      end_query_vgpu10(svga, sq);
1006      break;
1007   case SVGA_QUERY_NUM_DRAW_CALLS:
1008      sq->end_count = svga->hud.num_draw_calls;
1009      break;
1010   case SVGA_QUERY_NUM_FALLBACKS:
1011      sq->end_count = svga->hud.num_fallbacks;
1012      break;
1013   case SVGA_QUERY_NUM_FLUSHES:
1014      sq->end_count = svga->hud.num_flushes;
1015      break;
1016   case SVGA_QUERY_NUM_VALIDATIONS:
1017      sq->end_count = svga->hud.num_validations;
1018      break;
1019   case SVGA_QUERY_MAP_BUFFER_TIME:
1020      sq->end_count = svga->hud.map_buffer_time;
1021      break;
1022   case SVGA_QUERY_NUM_BUFFERS_MAPPED:
1023      sq->end_count = svga->hud.num_buffers_mapped;
1024      break;
1025   case SVGA_QUERY_NUM_TEXTURES_MAPPED:
1026      sq->end_count = svga->hud.num_textures_mapped;
1027      break;
1028   case SVGA_QUERY_NUM_BYTES_UPLOADED:
1029      sq->end_count = svga->hud.num_bytes_uploaded;
1030      break;
1031   case SVGA_QUERY_NUM_COMMAND_BUFFERS:
1032      sq->end_count = svga->swc->num_command_buffers;
1033      break;
1034   case SVGA_QUERY_COMMAND_BUFFER_SIZE:
1035      sq->end_count = svga->hud.command_buffer_size;
1036      break;
1037   case SVGA_QUERY_FLUSH_TIME:
1038      sq->end_count = svga->hud.flush_time;
1039      break;
1040   case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
1041      sq->end_count = svga->hud.surface_write_flushes;
1042      break;
1043   case SVGA_QUERY_NUM_READBACKS:
1044      sq->end_count = svga->hud.num_readbacks;
1045      break;
1046   case SVGA_QUERY_NUM_RESOURCE_UPDATES:
1047      sq->end_count = svga->hud.num_resource_updates;
1048      break;
1049   case SVGA_QUERY_NUM_BUFFER_UPLOADS:
1050      sq->end_count = svga->hud.num_buffer_uploads;
1051      break;
1052   case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
1053      sq->end_count = svga->hud.num_const_buf_updates;
1054      break;
1055   case SVGA_QUERY_NUM_CONST_UPDATES:
1056      sq->end_count = svga->hud.num_const_updates;
1057      break;
1058   case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
1059      sq->end_count = svga->swc->num_shader_reloc;
1060      break;
1061   case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
1062      sq->end_count = svga->swc->num_surf_reloc;
1063      break;
1064   case SVGA_QUERY_MEMORY_USED:
1065   case SVGA_QUERY_NUM_SHADERS:
1066   case SVGA_QUERY_NUM_RESOURCES:
1067   case SVGA_QUERY_NUM_STATE_OBJECTS:
1068   case SVGA_QUERY_NUM_SURFACE_VIEWS:
1069   case SVGA_QUERY_NUM_GENERATE_MIPMAP:
1070   case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
1071   case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
1072   case SVGA_QUERY_SHADER_MEM_USED:
1073      /* nothing */
1074      break;
1075   default:
1076      assert(!"unexpected query type in svga_end_query()");
1077   }
1078   sq->active = FALSE;
1079   return true;
1080}
1081
1082
1083static bool
1084svga_get_query_result(struct pipe_context *pipe,
1085                      struct pipe_query *q,
1086                      bool wait,
1087                      union pipe_query_result *vresult)
1088{
1089   struct svga_screen *svgascreen = svga_screen(pipe->screen);
1090   struct svga_context *svga = svga_context(pipe);
1091   struct svga_query *sq = svga_query(q);
1092   uint64_t *result = (uint64_t *)vresult;
1093   bool ret = true;
1094
1095   assert(sq);
1096
1097   SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d wait: %d\n",
1098            __FUNCTION__, sq, sq->id, wait);
1099
1100   switch (sq->type) {
1101   case PIPE_QUERY_OCCLUSION_COUNTER:
1102      if (svga_have_vgpu10(svga)) {
1103         SVGADXOcclusionQueryResult occResult;
1104         ret = get_query_result_vgpu10(svga, sq, wait,
1105                                       (void *)&occResult, sizeof(occResult));
1106         *result = (uint64_t)occResult.samplesRendered;
1107      } else {
1108         ret = get_query_result_vgpu9(svga, sq, wait, result);
1109      }
1110      break;
1111   case PIPE_QUERY_OCCLUSION_PREDICATE:
1112   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: {
1113      if (svga_have_vgpu10(svga)) {
1114         SVGADXOcclusionPredicateQueryResult occResult;
1115         ret = get_query_result_vgpu10(svga, sq, wait,
1116                                       (void *)&occResult, sizeof(occResult));
1117         vresult->b = occResult.anySamplesRendered != 0;
1118      } else {
1119         uint64_t count = 0;
1120         ret = get_query_result_vgpu9(svga, sq, wait, &count);
1121         vresult->b = count != 0;
1122      }
1123      break;
1124   }
1125   case PIPE_QUERY_SO_STATISTICS: {
1126      SVGADXStreamOutStatisticsQueryResult sResult;
1127      struct pipe_query_data_so_statistics *pResult =
1128         (struct pipe_query_data_so_statistics *)vresult;
1129
1130      assert(svga_have_vgpu10(svga));
1131      ret = get_query_result_vgpu10(svga, sq, wait,
1132                                    (void *)&sResult, sizeof(sResult));
1133      pResult->num_primitives_written = sResult.numPrimitivesWritten;
1134      pResult->primitives_storage_needed = sResult.numPrimitivesRequired;
1135      break;
1136   }
1137   case PIPE_QUERY_TIMESTAMP: {
1138      SVGADXTimestampQueryResult sResult;
1139
1140      assert(svga_have_vgpu10(svga));
1141      ret = get_query_result_vgpu10(svga, sq, wait,
1142                                    (void *)&sResult, sizeof(sResult));
1143      *result = (uint64_t)sResult.timestamp;
1144      break;
1145   }
1146   case PIPE_QUERY_PRIMITIVES_GENERATED: {
1147      SVGADXStreamOutStatisticsQueryResult sResult;
1148
1149      assert(svga_have_vgpu10(svga));
1150      ret = get_query_result_vgpu10(svga, sq, wait,
1151                                    (void *)&sResult, sizeof sResult);
1152      *result = (uint64_t)sResult.numPrimitivesRequired;
1153      break;
1154   }
1155   case PIPE_QUERY_PRIMITIVES_EMITTED: {
1156      SVGADXStreamOutStatisticsQueryResult sResult;
1157
1158      assert(svga_have_vgpu10(svga));
1159      ret = get_query_result_vgpu10(svga, sq, wait,
1160                                    (void *)&sResult, sizeof sResult);
1161      *result = (uint64_t)sResult.numPrimitivesWritten;
1162      break;
1163   }
1164   /* These are per-frame counters */
1165   case SVGA_QUERY_NUM_DRAW_CALLS:
1166   case SVGA_QUERY_NUM_FALLBACKS:
1167   case SVGA_QUERY_NUM_FLUSHES:
1168   case SVGA_QUERY_NUM_VALIDATIONS:
1169   case SVGA_QUERY_MAP_BUFFER_TIME:
1170   case SVGA_QUERY_NUM_BUFFERS_MAPPED:
1171   case SVGA_QUERY_NUM_TEXTURES_MAPPED:
1172   case SVGA_QUERY_NUM_BYTES_UPLOADED:
1173   case SVGA_QUERY_NUM_COMMAND_BUFFERS:
1174   case SVGA_QUERY_COMMAND_BUFFER_SIZE:
1175   case SVGA_QUERY_FLUSH_TIME:
1176   case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
1177   case SVGA_QUERY_NUM_READBACKS:
1178   case SVGA_QUERY_NUM_RESOURCE_UPDATES:
1179   case SVGA_QUERY_NUM_BUFFER_UPLOADS:
1180   case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
1181   case SVGA_QUERY_NUM_CONST_UPDATES:
1182   case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
1183   case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
1184      vresult->u64 = sq->end_count - sq->begin_count;
1185      break;
1186   /* These are running total counters */
1187   case SVGA_QUERY_MEMORY_USED:
1188      vresult->u64 = svgascreen->hud.total_resource_bytes;
1189      break;
1190   case SVGA_QUERY_NUM_SHADERS:
1191      vresult->u64 = svga->hud.num_shaders;
1192      break;
1193   case SVGA_QUERY_NUM_RESOURCES:
1194      vresult->u64 = svgascreen->hud.num_resources;
1195      break;
1196   case SVGA_QUERY_NUM_STATE_OBJECTS:
1197      vresult->u64 = (svga->hud.num_blend_objects +
1198                      svga->hud.num_depthstencil_objects +
1199                      svga->hud.num_rasterizer_objects +
1200                      svga->hud.num_sampler_objects +
1201                      svga->hud.num_samplerview_objects +
1202                      svga->hud.num_vertexelement_objects);
1203      break;
1204   case SVGA_QUERY_NUM_SURFACE_VIEWS:
1205      vresult->u64 = svga->hud.num_surface_views;
1206      break;
1207   case SVGA_QUERY_NUM_GENERATE_MIPMAP:
1208      vresult->u64 = svga->hud.num_generate_mipmap;
1209      break;
1210   case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
1211      vresult->u64 = svgascreen->hud.num_failed_allocations;
1212      break;
1213   case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
1214      vresult->f = (float) svga->swc->num_commands
1215         / (float) svga->swc->num_draw_commands;
1216      break;
1217   case SVGA_QUERY_SHADER_MEM_USED:
1218      vresult->u64 = svga->hud.shader_mem_used;
1219      break;
1220   default:
1221      assert(!"unexpected query type in svga_get_query_result");
1222   }
1223
1224   SVGA_DBG(DEBUG_QUERY, "%s result %d\n", __FUNCTION__, *((uint64_t *)vresult));
1225
1226   return ret;
1227}
1228
1229static void
1230svga_render_condition(struct pipe_context *pipe, struct pipe_query *q,
1231                      bool condition, enum pipe_render_cond_flag mode)
1232{
1233   struct svga_context *svga = svga_context(pipe);
1234   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
1235   struct svga_query *sq = svga_query(q);
1236   SVGA3dQueryId queryId;
1237
1238   SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
1239
1240   assert(svga_have_vgpu10(svga));
1241   if (sq == NULL) {
1242      queryId = SVGA3D_INVALID_ID;
1243   }
1244   else {
1245      assert(sq->svga_type == SVGA3D_QUERYTYPE_OCCLUSION ||
1246             sq->svga_type == SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE);
1247
1248      if (sq->svga_type == SVGA3D_QUERYTYPE_OCCLUSION) {
1249         assert(sq->predicate);
1250         /**
1251          * For conditional rendering, make sure to use the associated
1252          * predicate query.
1253          */
1254         sq = svga_query(sq->predicate);
1255      }
1256      queryId = sq->id;
1257
1258      if ((mode == PIPE_RENDER_COND_WAIT ||
1259           mode == PIPE_RENDER_COND_BY_REGION_WAIT) && sq->fence) {
1260         sws->fence_finish(sws, sq->fence, PIPE_TIMEOUT_INFINITE,
1261                           SVGA_FENCE_FLAG_QUERY);
1262      }
1263   }
1264   /*
1265    * if the kernel module doesn't support the predication command,
1266    * we'll just render unconditionally.
1267    * This is probably acceptable for the typical case of occlusion culling.
1268    */
1269   if (sws->have_set_predication_cmd) {
1270      SVGA_RETRY(svga, SVGA3D_vgpu10_SetPredication(svga->swc, queryId,
1271                                                    (uint32) condition));
1272      svga->pred.query_id = queryId;
1273      svga->pred.cond = condition;
1274   }
1275
1276   svga->render_condition = (sq != NULL);
1277}
1278
1279
1280/*
1281 * This function is a workaround because we lack the ability to query
1282 * renderer's time synchronously.
1283 */
1284static uint64_t
1285svga_get_timestamp(struct pipe_context *pipe)
1286{
1287   struct pipe_query *q = svga_create_query(pipe, PIPE_QUERY_TIMESTAMP, 0);
1288   union pipe_query_result result;
1289
1290   util_query_clear_result(&result, PIPE_QUERY_TIMESTAMP);
1291   svga_begin_query(pipe, q);
1292   svga_end_query(pipe,q);
1293   svga_get_query_result(pipe, q, TRUE, &result);
1294   svga_destroy_query(pipe, q);
1295
1296   return result.u64;
1297}
1298
1299
1300static void
1301svga_set_active_query_state(struct pipe_context *pipe, bool enable)
1302{
1303}
1304
1305
1306/**
1307 * \brief Toggle conditional rendering if already enabled
1308 *
1309 * \param svga[in]  The svga context
1310 * \param render_condition_enabled[in]  Whether to ignore requests to turn
1311 * conditional rendering off
1312 * \param on[in]  Whether to turn conditional rendering on or off
1313 */
1314void
1315svga_toggle_render_condition(struct svga_context *svga,
1316                             boolean render_condition_enabled,
1317                             boolean on)
1318{
1319   SVGA3dQueryId query_id;
1320
1321   if (render_condition_enabled ||
1322       svga->pred.query_id == SVGA3D_INVALID_ID) {
1323      return;
1324   }
1325
1326   /*
1327    * If we get here, it means that the system supports
1328    * conditional rendering since svga->pred.query_id has already been
1329    * modified for this context and thus support has already been
1330    * verified.
1331    */
1332   query_id = on ? svga->pred.query_id : SVGA3D_INVALID_ID;
1333
1334   SVGA_RETRY(svga, SVGA3D_vgpu10_SetPredication(svga->swc, query_id,
1335                                                 (uint32) svga->pred.cond));
1336}
1337
1338
1339void
1340svga_init_query_functions(struct svga_context *svga)
1341{
1342   svga->pipe.create_query = svga_create_query;
1343   svga->pipe.destroy_query = svga_destroy_query;
1344   svga->pipe.begin_query = svga_begin_query;
1345   svga->pipe.end_query = svga_end_query;
1346   svga->pipe.get_query_result = svga_get_query_result;
1347   svga->pipe.set_active_query_state = svga_set_active_query_state;
1348   svga->pipe.render_condition = svga_render_condition;
1349   svga->pipe.get_timestamp = svga_get_timestamp;
1350}
1351