1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc.
4bf215546Sopenharmony_ci * Copyright 2010 VMware, Inc.
5bf215546Sopenharmony_ci * All Rights Reserved.
6bf215546Sopenharmony_ci *
7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
9bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
10bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
11bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
12bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
13bf215546Sopenharmony_ci * the following conditions:
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
16bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
17bf215546Sopenharmony_ci * of the Software.
18bf215546Sopenharmony_ci *
19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22bf215546Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
23bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26bf215546Sopenharmony_ci *
27bf215546Sopenharmony_ci **************************************************************************/
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci/* Authors:
30bf215546Sopenharmony_ci *    Keith Whitwell, Qicheng Christopher Li, Brian Paul
31bf215546Sopenharmony_ci */
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "draw/draw_context.h"
34bf215546Sopenharmony_ci#include "pipe/p_defines.h"
35bf215546Sopenharmony_ci#include "util/u_memory.h"
36bf215546Sopenharmony_ci#include "util/os_time.h"
37bf215546Sopenharmony_ci#include "lp_context.h"
38bf215546Sopenharmony_ci#include "lp_flush.h"
39bf215546Sopenharmony_ci#include "lp_fence.h"
40bf215546Sopenharmony_ci#include "lp_query.h"
41bf215546Sopenharmony_ci#include "lp_screen.h"
42bf215546Sopenharmony_ci#include "lp_state.h"
43bf215546Sopenharmony_ci#include "lp_rast.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_cistatic struct llvmpipe_query *llvmpipe_query( struct pipe_query *p )
47bf215546Sopenharmony_ci{
48bf215546Sopenharmony_ci   return (struct llvmpipe_query *)p;
49bf215546Sopenharmony_ci}
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_cistatic struct pipe_query *
52bf215546Sopenharmony_cillvmpipe_create_query(struct pipe_context *pipe,
53bf215546Sopenharmony_ci                      unsigned type,
54bf215546Sopenharmony_ci                      unsigned index)
55bf215546Sopenharmony_ci{
56bf215546Sopenharmony_ci   struct llvmpipe_query *pq;
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci   assert(type < PIPE_QUERY_TYPES);
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci   pq = CALLOC_STRUCT( llvmpipe_query );
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   if (pq) {
63bf215546Sopenharmony_ci      pq->type = type;
64bf215546Sopenharmony_ci      pq->index = index;
65bf215546Sopenharmony_ci   }
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   return (struct pipe_query *) pq;
68bf215546Sopenharmony_ci}
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_cistatic void
72bf215546Sopenharmony_cillvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
73bf215546Sopenharmony_ci{
74bf215546Sopenharmony_ci   struct llvmpipe_query *pq = llvmpipe_query(q);
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   /* Ideally we would refcount queries & not get destroyed until the
77bf215546Sopenharmony_ci    * last scene had finished with us.
78bf215546Sopenharmony_ci    */
79bf215546Sopenharmony_ci   if (pq->fence) {
80bf215546Sopenharmony_ci      if (!lp_fence_issued(pq->fence))
81bf215546Sopenharmony_ci         llvmpipe_flush(pipe, NULL, __FUNCTION__);
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci      if (!lp_fence_signalled(pq->fence))
84bf215546Sopenharmony_ci         lp_fence_wait(pq->fence);
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci      lp_fence_reference(&pq->fence, NULL);
87bf215546Sopenharmony_ci   }
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   FREE(pq);
90bf215546Sopenharmony_ci}
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_cistatic bool
94bf215546Sopenharmony_cillvmpipe_get_query_result(struct pipe_context *pipe,
95bf215546Sopenharmony_ci                          struct pipe_query *q,
96bf215546Sopenharmony_ci                          bool wait,
97bf215546Sopenharmony_ci                          union pipe_query_result *vresult)
98bf215546Sopenharmony_ci{
99bf215546Sopenharmony_ci   struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
100bf215546Sopenharmony_ci   unsigned num_threads = MAX2(1, screen->num_threads);
101bf215546Sopenharmony_ci   struct llvmpipe_query *pq = llvmpipe_query(q);
102bf215546Sopenharmony_ci   uint64_t *result = (uint64_t *)vresult;
103bf215546Sopenharmony_ci   int i;
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   if (pq->fence) {
106bf215546Sopenharmony_ci      /* only have a fence if there was a scene */
107bf215546Sopenharmony_ci      if (!lp_fence_signalled(pq->fence)) {
108bf215546Sopenharmony_ci         if (!lp_fence_issued(pq->fence))
109bf215546Sopenharmony_ci            llvmpipe_flush(pipe, NULL, __FUNCTION__);
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci         if (!wait)
112bf215546Sopenharmony_ci            return false;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci         lp_fence_wait(pq->fence);
115bf215546Sopenharmony_ci      }
116bf215546Sopenharmony_ci   }
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   /* Sum the results from each of the threads:
119bf215546Sopenharmony_ci    */
120bf215546Sopenharmony_ci   *result = 0;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   switch (pq->type) {
123bf215546Sopenharmony_ci   case PIPE_QUERY_OCCLUSION_COUNTER:
124bf215546Sopenharmony_ci      for (i = 0; i < num_threads; i++) {
125bf215546Sopenharmony_ci         *result += pq->end[i];
126bf215546Sopenharmony_ci      }
127bf215546Sopenharmony_ci      break;
128bf215546Sopenharmony_ci   case PIPE_QUERY_OCCLUSION_PREDICATE:
129bf215546Sopenharmony_ci   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
130bf215546Sopenharmony_ci      for (i = 0; i < num_threads; i++) {
131bf215546Sopenharmony_ci         /* safer (still not guaranteed) when there's an overflow */
132bf215546Sopenharmony_ci         vresult->b = vresult->b || pq->end[i];
133bf215546Sopenharmony_ci      }
134bf215546Sopenharmony_ci      break;
135bf215546Sopenharmony_ci   case PIPE_QUERY_TIMESTAMP:
136bf215546Sopenharmony_ci      for (i = 0; i < num_threads; i++) {
137bf215546Sopenharmony_ci         if (pq->end[i] > *result) {
138bf215546Sopenharmony_ci            *result = pq->end[i];
139bf215546Sopenharmony_ci         }
140bf215546Sopenharmony_ci      }
141bf215546Sopenharmony_ci      break;
142bf215546Sopenharmony_ci   case PIPE_QUERY_TIME_ELAPSED: {
143bf215546Sopenharmony_ci      uint64_t start = (uint64_t)-1, end = 0;
144bf215546Sopenharmony_ci      for (i = 0; i < num_threads; i++) {
145bf215546Sopenharmony_ci         if (pq->start[i] && pq->start[i] < start)
146bf215546Sopenharmony_ci            start = pq->start[i];
147bf215546Sopenharmony_ci         if (pq->end[i] && pq->end[i] > end)
148bf215546Sopenharmony_ci            end = pq->end[i];
149bf215546Sopenharmony_ci      }
150bf215546Sopenharmony_ci      *result = end - start;
151bf215546Sopenharmony_ci      break;
152bf215546Sopenharmony_ci   }
153bf215546Sopenharmony_ci   case PIPE_QUERY_TIMESTAMP_DISJOINT: {
154bf215546Sopenharmony_ci      struct pipe_query_data_timestamp_disjoint *td =
155bf215546Sopenharmony_ci         (struct pipe_query_data_timestamp_disjoint *)vresult;
156bf215546Sopenharmony_ci      /* os_get_time_nano return nanoseconds */
157bf215546Sopenharmony_ci      td->frequency = UINT64_C(1000000000);
158bf215546Sopenharmony_ci      td->disjoint = false;
159bf215546Sopenharmony_ci   }
160bf215546Sopenharmony_ci      break;
161bf215546Sopenharmony_ci   case PIPE_QUERY_GPU_FINISHED:
162bf215546Sopenharmony_ci      vresult->b = true;
163bf215546Sopenharmony_ci      break;
164bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_GENERATED:
165bf215546Sopenharmony_ci      *result = pq->num_primitives_generated[0];
166bf215546Sopenharmony_ci      break;
167bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_EMITTED:
168bf215546Sopenharmony_ci      *result = pq->num_primitives_written[0];
169bf215546Sopenharmony_ci      break;
170bf215546Sopenharmony_ci   case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
171bf215546Sopenharmony_ci      vresult->b = false;
172bf215546Sopenharmony_ci      for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++)
173bf215546Sopenharmony_ci         vresult->b |= pq->num_primitives_generated[s] > pq->num_primitives_written[s];
174bf215546Sopenharmony_ci      break;
175bf215546Sopenharmony_ci   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
176bf215546Sopenharmony_ci      vresult->b = pq->num_primitives_generated[0] > pq->num_primitives_written[0];
177bf215546Sopenharmony_ci      break;
178bf215546Sopenharmony_ci   case PIPE_QUERY_SO_STATISTICS: {
179bf215546Sopenharmony_ci      struct pipe_query_data_so_statistics *stats =
180bf215546Sopenharmony_ci         (struct pipe_query_data_so_statistics *)vresult;
181bf215546Sopenharmony_ci      stats->num_primitives_written = pq->num_primitives_written[0];
182bf215546Sopenharmony_ci      stats->primitives_storage_needed = pq->num_primitives_generated[0];
183bf215546Sopenharmony_ci   }
184bf215546Sopenharmony_ci      break;
185bf215546Sopenharmony_ci   case PIPE_QUERY_PIPELINE_STATISTICS: {
186bf215546Sopenharmony_ci      struct pipe_query_data_pipeline_statistics *stats =
187bf215546Sopenharmony_ci         (struct pipe_query_data_pipeline_statistics *)vresult;
188bf215546Sopenharmony_ci      /* only ps_invocations come from binned query */
189bf215546Sopenharmony_ci      for (i = 0; i < num_threads; i++) {
190bf215546Sopenharmony_ci         pq->stats.ps_invocations += pq->end[i];
191bf215546Sopenharmony_ci      }
192bf215546Sopenharmony_ci      pq->stats.ps_invocations *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE;
193bf215546Sopenharmony_ci      *stats = pq->stats;
194bf215546Sopenharmony_ci   }
195bf215546Sopenharmony_ci      break;
196bf215546Sopenharmony_ci   default:
197bf215546Sopenharmony_ci      assert(0);
198bf215546Sopenharmony_ci      break;
199bf215546Sopenharmony_ci   }
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   return true;
202bf215546Sopenharmony_ci}
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_cistatic void
205bf215546Sopenharmony_cillvmpipe_get_query_result_resource(struct pipe_context *pipe,
206bf215546Sopenharmony_ci                                   struct pipe_query *q,
207bf215546Sopenharmony_ci                                   enum pipe_query_flags flags,
208bf215546Sopenharmony_ci                                   enum pipe_query_value_type result_type,
209bf215546Sopenharmony_ci                                   int index,
210bf215546Sopenharmony_ci                                   struct pipe_resource *resource,
211bf215546Sopenharmony_ci                                   unsigned offset)
212bf215546Sopenharmony_ci{
213bf215546Sopenharmony_ci   struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
214bf215546Sopenharmony_ci   unsigned num_threads = MAX2(1, screen->num_threads);
215bf215546Sopenharmony_ci   struct llvmpipe_query *pq = llvmpipe_query(q);
216bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
217bf215546Sopenharmony_ci   bool unsignalled = false;
218bf215546Sopenharmony_ci   if (pq->fence) {
219bf215546Sopenharmony_ci      /* only have a fence if there was a scene */
220bf215546Sopenharmony_ci      if (!lp_fence_signalled(pq->fence)) {
221bf215546Sopenharmony_ci         if (!lp_fence_issued(pq->fence))
222bf215546Sopenharmony_ci            llvmpipe_flush(pipe, NULL, __FUNCTION__);
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci         if (flags & PIPE_QUERY_WAIT)
225bf215546Sopenharmony_ci            lp_fence_wait(pq->fence);
226bf215546Sopenharmony_ci      }
227bf215546Sopenharmony_ci      unsignalled = !lp_fence_signalled(pq->fence);
228bf215546Sopenharmony_ci   }
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   uint64_t value = 0, value2 = 0;
232bf215546Sopenharmony_ci   unsigned num_values = 1;
233bf215546Sopenharmony_ci   if (index == -1)
234bf215546Sopenharmony_ci      if (unsignalled)
235bf215546Sopenharmony_ci         value = 0;
236bf215546Sopenharmony_ci      else
237bf215546Sopenharmony_ci         value = 1;
238bf215546Sopenharmony_ci   else {
239bf215546Sopenharmony_ci      unsigned i;
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci      /* don't write a value if fence hasn't signalled,
242bf215546Sopenharmony_ci         and partial isn't set . */
243bf215546Sopenharmony_ci      if (unsignalled && !(flags & PIPE_QUERY_PARTIAL))
244bf215546Sopenharmony_ci         return;
245bf215546Sopenharmony_ci      switch (pq->type) {
246bf215546Sopenharmony_ci      case PIPE_QUERY_OCCLUSION_COUNTER:
247bf215546Sopenharmony_ci         for (i = 0; i < num_threads; i++) {
248bf215546Sopenharmony_ci            value += pq->end[i];
249bf215546Sopenharmony_ci         }
250bf215546Sopenharmony_ci         break;
251bf215546Sopenharmony_ci      case PIPE_QUERY_OCCLUSION_PREDICATE:
252bf215546Sopenharmony_ci      case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
253bf215546Sopenharmony_ci         for (i = 0; i < num_threads; i++) {
254bf215546Sopenharmony_ci            /* safer (still not guaranteed) when there's an overflow */
255bf215546Sopenharmony_ci            value = value || pq->end[i];
256bf215546Sopenharmony_ci         }
257bf215546Sopenharmony_ci         break;
258bf215546Sopenharmony_ci      case PIPE_QUERY_PRIMITIVES_GENERATED:
259bf215546Sopenharmony_ci         value = pq->num_primitives_generated[0];
260bf215546Sopenharmony_ci         break;
261bf215546Sopenharmony_ci      case PIPE_QUERY_PRIMITIVES_EMITTED:
262bf215546Sopenharmony_ci         value = pq->num_primitives_written[0];
263bf215546Sopenharmony_ci         break;
264bf215546Sopenharmony_ci      case PIPE_QUERY_TIMESTAMP:
265bf215546Sopenharmony_ci         for (i = 0; i < num_threads; i++) {
266bf215546Sopenharmony_ci            if (pq->end[i] > value) {
267bf215546Sopenharmony_ci               value = pq->end[i];
268bf215546Sopenharmony_ci            }
269bf215546Sopenharmony_ci         }
270bf215546Sopenharmony_ci         break;
271bf215546Sopenharmony_ci      case PIPE_QUERY_TIME_ELAPSED: {
272bf215546Sopenharmony_ci         uint64_t start = (uint64_t)-1, end = 0;
273bf215546Sopenharmony_ci         for (i = 0; i < num_threads; i++) {
274bf215546Sopenharmony_ci            if (pq->start[i] && pq->start[i] < start)
275bf215546Sopenharmony_ci               start = pq->start[i];
276bf215546Sopenharmony_ci            if (pq->end[i] && pq->end[i] > end)
277bf215546Sopenharmony_ci               end = pq->end[i];
278bf215546Sopenharmony_ci         }
279bf215546Sopenharmony_ci         value = end - start;
280bf215546Sopenharmony_ci         break;
281bf215546Sopenharmony_ci      }
282bf215546Sopenharmony_ci      case PIPE_QUERY_SO_STATISTICS:
283bf215546Sopenharmony_ci         value = pq->num_primitives_written[0];
284bf215546Sopenharmony_ci         value2 = pq->num_primitives_generated[0];
285bf215546Sopenharmony_ci         num_values = 2;
286bf215546Sopenharmony_ci         break;
287bf215546Sopenharmony_ci      case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
288bf215546Sopenharmony_ci         value = 0;
289bf215546Sopenharmony_ci         for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++)
290bf215546Sopenharmony_ci            value |= !!(pq->num_primitives_generated[s] > pq->num_primitives_written[s]);
291bf215546Sopenharmony_ci         break;
292bf215546Sopenharmony_ci      case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
293bf215546Sopenharmony_ci         value = !!(pq->num_primitives_generated[0] > pq->num_primitives_written[0]);
294bf215546Sopenharmony_ci         break;
295bf215546Sopenharmony_ci      case PIPE_QUERY_PIPELINE_STATISTICS:
296bf215546Sopenharmony_ci         switch ((enum pipe_statistics_query_index)index) {
297bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_IA_VERTICES:
298bf215546Sopenharmony_ci            value = pq->stats.ia_vertices;
299bf215546Sopenharmony_ci            break;
300bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_IA_PRIMITIVES:
301bf215546Sopenharmony_ci            value = pq->stats.ia_primitives;
302bf215546Sopenharmony_ci            break;
303bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_VS_INVOCATIONS:
304bf215546Sopenharmony_ci            value = pq->stats.vs_invocations;
305bf215546Sopenharmony_ci            break;
306bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_GS_INVOCATIONS:
307bf215546Sopenharmony_ci            value = pq->stats.gs_invocations;
308bf215546Sopenharmony_ci            break;
309bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_GS_PRIMITIVES:
310bf215546Sopenharmony_ci            value = pq->stats.gs_primitives;
311bf215546Sopenharmony_ci            break;
312bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_C_INVOCATIONS:
313bf215546Sopenharmony_ci            value = pq->stats.c_invocations;
314bf215546Sopenharmony_ci            break;
315bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_C_PRIMITIVES:
316bf215546Sopenharmony_ci            value = pq->stats.c_primitives;
317bf215546Sopenharmony_ci            break;
318bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_PS_INVOCATIONS:
319bf215546Sopenharmony_ci            value = 0;
320bf215546Sopenharmony_ci            for (i = 0; i < num_threads; i++) {
321bf215546Sopenharmony_ci               value += pq->end[i];
322bf215546Sopenharmony_ci            }
323bf215546Sopenharmony_ci            value *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE;
324bf215546Sopenharmony_ci            break;
325bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_HS_INVOCATIONS:
326bf215546Sopenharmony_ci            value = pq->stats.hs_invocations;
327bf215546Sopenharmony_ci            break;
328bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_DS_INVOCATIONS:
329bf215546Sopenharmony_ci            value = pq->stats.ds_invocations;
330bf215546Sopenharmony_ci            break;
331bf215546Sopenharmony_ci         case PIPE_STAT_QUERY_CS_INVOCATIONS:
332bf215546Sopenharmony_ci            value = pq->stats.cs_invocations;
333bf215546Sopenharmony_ci            break;
334bf215546Sopenharmony_ci         }
335bf215546Sopenharmony_ci         break;
336bf215546Sopenharmony_ci      default:
337bf215546Sopenharmony_ci         fprintf(stderr, "Unknown query type %d\n", pq->type);
338bf215546Sopenharmony_ci         break;
339bf215546Sopenharmony_ci      }
340bf215546Sopenharmony_ci   }
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci   void *dst = (uint8_t *)lpr->data + offset;
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_values; i++) {
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci      if (i == 1) {
347bf215546Sopenharmony_ci         value = value2;
348bf215546Sopenharmony_ci         dst = (char *)dst + ((result_type == PIPE_QUERY_TYPE_I64 ||
349bf215546Sopenharmony_ci                               result_type == PIPE_QUERY_TYPE_U64) ? 8 : 4);
350bf215546Sopenharmony_ci      }
351bf215546Sopenharmony_ci      switch (result_type) {
352bf215546Sopenharmony_ci      case PIPE_QUERY_TYPE_I32: {
353bf215546Sopenharmony_ci         int32_t *iptr = (int32_t *)dst;
354bf215546Sopenharmony_ci         if (value > 0x7fffffff)
355bf215546Sopenharmony_ci            *iptr = 0x7fffffff;
356bf215546Sopenharmony_ci         else
357bf215546Sopenharmony_ci            *iptr = (int32_t)value;
358bf215546Sopenharmony_ci         break;
359bf215546Sopenharmony_ci      }
360bf215546Sopenharmony_ci      case PIPE_QUERY_TYPE_U32: {
361bf215546Sopenharmony_ci         uint32_t *uptr = (uint32_t *)dst;
362bf215546Sopenharmony_ci         if (value > 0xffffffff)
363bf215546Sopenharmony_ci            *uptr = 0xffffffff;
364bf215546Sopenharmony_ci         else
365bf215546Sopenharmony_ci            *uptr = (uint32_t)value;
366bf215546Sopenharmony_ci         break;
367bf215546Sopenharmony_ci      }
368bf215546Sopenharmony_ci      case PIPE_QUERY_TYPE_I64: {
369bf215546Sopenharmony_ci         int64_t *iptr = (int64_t *)dst;
370bf215546Sopenharmony_ci         *iptr = (int64_t)value;
371bf215546Sopenharmony_ci         break;
372bf215546Sopenharmony_ci      }
373bf215546Sopenharmony_ci      case PIPE_QUERY_TYPE_U64: {
374bf215546Sopenharmony_ci         uint64_t *uptr = (uint64_t *)dst;
375bf215546Sopenharmony_ci         *uptr = (uint64_t)value;
376bf215546Sopenharmony_ci         break;
377bf215546Sopenharmony_ci      }
378bf215546Sopenharmony_ci      }
379bf215546Sopenharmony_ci   }
380bf215546Sopenharmony_ci}
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_cistatic bool
383bf215546Sopenharmony_cillvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
384bf215546Sopenharmony_ci{
385bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
386bf215546Sopenharmony_ci   struct llvmpipe_query *pq = llvmpipe_query(q);
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci   /* Check if the query is already in the scene.  If so, we need to
389bf215546Sopenharmony_ci    * flush the scene now.  Real apps shouldn't re-use a query in a
390bf215546Sopenharmony_ci    * frame of rendering.
391bf215546Sopenharmony_ci    */
392bf215546Sopenharmony_ci   if (pq->fence && !lp_fence_issued(pq->fence)) {
393bf215546Sopenharmony_ci      llvmpipe_finish(pipe, __FUNCTION__);
394bf215546Sopenharmony_ci   }
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci   memset(pq->start, 0, sizeof(pq->start));
398bf215546Sopenharmony_ci   memset(pq->end, 0, sizeof(pq->end));
399bf215546Sopenharmony_ci   lp_setup_begin_query(llvmpipe->setup, pq);
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   switch (pq->type) {
402bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_EMITTED:
403bf215546Sopenharmony_ci      pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written;
404bf215546Sopenharmony_ci      break;
405bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_GENERATED:
406bf215546Sopenharmony_ci      pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed;
407bf215546Sopenharmony_ci      llvmpipe->active_primgen_queries++;
408bf215546Sopenharmony_ci      break;
409bf215546Sopenharmony_ci   case PIPE_QUERY_SO_STATISTICS:
410bf215546Sopenharmony_ci      pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written;
411bf215546Sopenharmony_ci      pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed;
412bf215546Sopenharmony_ci      break;
413bf215546Sopenharmony_ci   case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
414bf215546Sopenharmony_ci      for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) {
415bf215546Sopenharmony_ci         pq->num_primitives_written[s] = llvmpipe->so_stats[s].num_primitives_written;
416bf215546Sopenharmony_ci         pq->num_primitives_generated[s] = llvmpipe->so_stats[s].primitives_storage_needed;
417bf215546Sopenharmony_ci      }
418bf215546Sopenharmony_ci      break;
419bf215546Sopenharmony_ci   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
420bf215546Sopenharmony_ci      pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written;
421bf215546Sopenharmony_ci      pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed;
422bf215546Sopenharmony_ci      break;
423bf215546Sopenharmony_ci   case PIPE_QUERY_PIPELINE_STATISTICS:
424bf215546Sopenharmony_ci      /* reset our cache */
425bf215546Sopenharmony_ci      if (llvmpipe->active_statistics_queries == 0) {
426bf215546Sopenharmony_ci         memset(&llvmpipe->pipeline_statistics, 0,
427bf215546Sopenharmony_ci                sizeof(llvmpipe->pipeline_statistics));
428bf215546Sopenharmony_ci      }
429bf215546Sopenharmony_ci      memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats));
430bf215546Sopenharmony_ci      llvmpipe->active_statistics_queries++;
431bf215546Sopenharmony_ci      break;
432bf215546Sopenharmony_ci   case PIPE_QUERY_OCCLUSION_COUNTER:
433bf215546Sopenharmony_ci   case PIPE_QUERY_OCCLUSION_PREDICATE:
434bf215546Sopenharmony_ci   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
435bf215546Sopenharmony_ci      llvmpipe->active_occlusion_queries++;
436bf215546Sopenharmony_ci      llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
437bf215546Sopenharmony_ci      break;
438bf215546Sopenharmony_ci   default:
439bf215546Sopenharmony_ci      break;
440bf215546Sopenharmony_ci   }
441bf215546Sopenharmony_ci   return true;
442bf215546Sopenharmony_ci}
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_cistatic bool
446bf215546Sopenharmony_cillvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
447bf215546Sopenharmony_ci{
448bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
449bf215546Sopenharmony_ci   struct llvmpipe_query *pq = llvmpipe_query(q);
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   lp_setup_end_query(llvmpipe->setup, pq);
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci   switch (pq->type) {
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_EMITTED:
456bf215546Sopenharmony_ci      pq->num_primitives_written[0] =
457bf215546Sopenharmony_ci         llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0];
458bf215546Sopenharmony_ci      break;
459bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_GENERATED:
460bf215546Sopenharmony_ci      assert(llvmpipe->active_primgen_queries);
461bf215546Sopenharmony_ci      llvmpipe->active_primgen_queries--;
462bf215546Sopenharmony_ci      pq->num_primitives_generated[0] =
463bf215546Sopenharmony_ci         llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0];
464bf215546Sopenharmony_ci      break;
465bf215546Sopenharmony_ci   case PIPE_QUERY_SO_STATISTICS:
466bf215546Sopenharmony_ci      pq->num_primitives_written[0] =
467bf215546Sopenharmony_ci         llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0];
468bf215546Sopenharmony_ci      pq->num_primitives_generated[0] =
469bf215546Sopenharmony_ci         llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0];
470bf215546Sopenharmony_ci      break;
471bf215546Sopenharmony_ci   case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
472bf215546Sopenharmony_ci      for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) {
473bf215546Sopenharmony_ci         pq->num_primitives_written[s] =
474bf215546Sopenharmony_ci            llvmpipe->so_stats[s].num_primitives_written - pq->num_primitives_written[s];
475bf215546Sopenharmony_ci         pq->num_primitives_generated[s] =
476bf215546Sopenharmony_ci            llvmpipe->so_stats[s].primitives_storage_needed - pq->num_primitives_generated[s];
477bf215546Sopenharmony_ci      }
478bf215546Sopenharmony_ci      break;
479bf215546Sopenharmony_ci   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
480bf215546Sopenharmony_ci      pq->num_primitives_written[0] =
481bf215546Sopenharmony_ci         llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0];
482bf215546Sopenharmony_ci      pq->num_primitives_generated[0] =
483bf215546Sopenharmony_ci         llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0];
484bf215546Sopenharmony_ci      break;
485bf215546Sopenharmony_ci   case PIPE_QUERY_PIPELINE_STATISTICS:
486bf215546Sopenharmony_ci      pq->stats.ia_vertices =
487bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.ia_vertices - pq->stats.ia_vertices;
488bf215546Sopenharmony_ci      pq->stats.ia_primitives =
489bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.ia_primitives - pq->stats.ia_primitives;
490bf215546Sopenharmony_ci      pq->stats.vs_invocations =
491bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.vs_invocations - pq->stats.vs_invocations;
492bf215546Sopenharmony_ci      pq->stats.gs_invocations =
493bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.gs_invocations - pq->stats.gs_invocations;
494bf215546Sopenharmony_ci      pq->stats.gs_primitives =
495bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.gs_primitives - pq->stats.gs_primitives;
496bf215546Sopenharmony_ci      pq->stats.c_invocations =
497bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations;
498bf215546Sopenharmony_ci      pq->stats.c_primitives =
499bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives;
500bf215546Sopenharmony_ci      pq->stats.ps_invocations =
501bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations;
502bf215546Sopenharmony_ci      pq->stats.cs_invocations =
503bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.cs_invocations - pq->stats.cs_invocations;
504bf215546Sopenharmony_ci      pq->stats.hs_invocations =
505bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.hs_invocations - pq->stats.hs_invocations;
506bf215546Sopenharmony_ci      pq->stats.ds_invocations =
507bf215546Sopenharmony_ci         llvmpipe->pipeline_statistics.ds_invocations - pq->stats.ds_invocations;
508bf215546Sopenharmony_ci      llvmpipe->active_statistics_queries--;
509bf215546Sopenharmony_ci      break;
510bf215546Sopenharmony_ci   case PIPE_QUERY_OCCLUSION_COUNTER:
511bf215546Sopenharmony_ci   case PIPE_QUERY_OCCLUSION_PREDICATE:
512bf215546Sopenharmony_ci   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
513bf215546Sopenharmony_ci      assert(llvmpipe->active_occlusion_queries);
514bf215546Sopenharmony_ci      llvmpipe->active_occlusion_queries--;
515bf215546Sopenharmony_ci      llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
516bf215546Sopenharmony_ci      break;
517bf215546Sopenharmony_ci   default:
518bf215546Sopenharmony_ci      break;
519bf215546Sopenharmony_ci   }
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci   return true;
522bf215546Sopenharmony_ci}
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ciboolean
525bf215546Sopenharmony_cillvmpipe_check_render_cond(struct llvmpipe_context *lp)
526bf215546Sopenharmony_ci{
527bf215546Sopenharmony_ci   struct pipe_context *pipe = &lp->pipe;
528bf215546Sopenharmony_ci   boolean b, wait;
529bf215546Sopenharmony_ci   uint64_t result;
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci   if (lp->render_cond_buffer) {
532bf215546Sopenharmony_ci      uint32_t data = *(uint32_t *)((char *)lp->render_cond_buffer->data + lp->render_cond_offset);
533bf215546Sopenharmony_ci      return (!data) == lp->render_cond_cond;
534bf215546Sopenharmony_ci   }
535bf215546Sopenharmony_ci   if (!lp->render_cond_query)
536bf215546Sopenharmony_ci      return TRUE; /* no query predicate, draw normally */
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ci   wait = (lp->render_cond_mode == PIPE_RENDER_COND_WAIT ||
539bf215546Sopenharmony_ci           lp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci   b = pipe->get_query_result(pipe, lp->render_cond_query, wait, (void*)&result);
542bf215546Sopenharmony_ci   if (b)
543bf215546Sopenharmony_ci      return ((!result) == lp->render_cond_cond);
544bf215546Sopenharmony_ci   else
545bf215546Sopenharmony_ci      return TRUE;
546bf215546Sopenharmony_ci}
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_cistatic void
549bf215546Sopenharmony_cillvmpipe_set_active_query_state(struct pipe_context *pipe, bool enable)
550bf215546Sopenharmony_ci{
551bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_ci   llvmpipe->queries_disabled = !enable;
554bf215546Sopenharmony_ci   /* for OQs we need to regenerate the fragment shader */
555bf215546Sopenharmony_ci   llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
556bf215546Sopenharmony_ci}
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_civoid llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe )
559bf215546Sopenharmony_ci{
560bf215546Sopenharmony_ci   llvmpipe->pipe.create_query = llvmpipe_create_query;
561bf215546Sopenharmony_ci   llvmpipe->pipe.destroy_query = llvmpipe_destroy_query;
562bf215546Sopenharmony_ci   llvmpipe->pipe.begin_query = llvmpipe_begin_query;
563bf215546Sopenharmony_ci   llvmpipe->pipe.end_query = llvmpipe_end_query;
564bf215546Sopenharmony_ci   llvmpipe->pipe.get_query_result = llvmpipe_get_query_result;
565bf215546Sopenharmony_ci   llvmpipe->pipe.get_query_result_resource = llvmpipe_get_query_result_resource;
566bf215546Sopenharmony_ci   llvmpipe->pipe.set_active_query_state = llvmpipe_set_active_query_state;
567bf215546Sopenharmony_ci}
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ci
570