Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included
14
 * in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 * OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
 
26
#include "glheader.h"
27
#include "context.h"
28
#include "enums.h"
29
#include "hash.h"
30
#include "imports.h"
31
#include "queryobj.h"
32
#include "mtypes.h"
33
#include "main/dispatch.h"
34
 
35
 
36
/**
37
 * Allocate a new query object.  This is a fallback routine called via
38
 * ctx->Driver.NewQueryObject().
39
 * \param ctx - rendering context
40
 * \param id - the new object's ID
41
 * \return pointer to new query_object object or NULL if out of memory.
42
 */
43
static struct gl_query_object *
44
_mesa_new_query_object(struct gl_context *ctx, GLuint id)
45
{
46
   struct gl_query_object *q = MALLOC_STRUCT(gl_query_object);
47
   (void) ctx;
48
   if (q) {
49
      q->Id = id;
50
      q->Result = 0;
51
      q->Active = GL_FALSE;
52
 
53
      /* This is to satisfy the language of the specification: "In the initial
54
       * state of a query object, the result is available" (OpenGL 3.1 §
55
       * 2.13).
56
       */
57
      q->Ready = GL_TRUE;
58
 
59
      /* OpenGL 3.1 § 2.13 says about GenQueries, "These names are marked as
60
       * used, but no object is associated with them until the first time they
61
       * are used by BeginQuery." Since our implementation actually does
62
       * allocate an object at this point, use a flag to indicate that this
63
       * object has not yet been bound so should not be considered a query.
64
       */
65
      q->EverBound = GL_FALSE;
66
   }
67
   return q;
68
}
69
 
70
 
71
/**
72
 * Begin a query.  Software driver fallback.
73
 * Called via ctx->Driver.BeginQuery().
74
 */
75
static void
76
_mesa_begin_query(struct gl_context *ctx, struct gl_query_object *q)
77
{
78
   ctx->NewState |= _NEW_DEPTH; /* for swrast */
79
}
80
 
81
 
82
/**
83
 * End a query.  Software driver fallback.
84
 * Called via ctx->Driver.EndQuery().
85
 */
86
static void
87
_mesa_end_query(struct gl_context *ctx, struct gl_query_object *q)
88
{
89
   ctx->NewState |= _NEW_DEPTH; /* for swrast */
90
   q->Ready = GL_TRUE;
91
}
92
 
93
 
94
/**
95
 * Wait for query to complete.  Software driver fallback.
96
 * Called via ctx->Driver.WaitQuery().
97
 */
98
static void
99
_mesa_wait_query(struct gl_context *ctx, struct gl_query_object *q)
100
{
101
   /* For software drivers, _mesa_end_query() should have completed the query.
102
    * For real hardware, implement a proper WaitQuery() driver function,
103
    * which may require issuing a flush.
104
    */
105
   assert(q->Ready);
106
}
107
 
108
 
109
/**
110
 * Check if a query results are ready.  Software driver fallback.
111
 * Called via ctx->Driver.CheckQuery().
112
 */
113
static void
114
_mesa_check_query(struct gl_context *ctx, struct gl_query_object *q)
115
{
116
   /* No-op for sw rendering.
117
    * HW drivers may need to flush at this time.
118
    */
119
}
120
 
121
 
122
/**
123
 * Delete a query object.  Called via ctx->Driver.DeleteQuery().
124
 * Not removed from hash table here.
125
 */
126
static void
127
_mesa_delete_query(struct gl_context *ctx, struct gl_query_object *q)
128
{
129
   free(q);
130
}
131
 
132
 
133
void
134
_mesa_init_query_object_functions(struct dd_function_table *driver)
135
{
136
   driver->NewQueryObject = _mesa_new_query_object;
137
   driver->DeleteQuery = _mesa_delete_query;
138
   driver->BeginQuery = _mesa_begin_query;
139
   driver->EndQuery = _mesa_end_query;
140
   driver->WaitQuery = _mesa_wait_query;
141
   driver->CheckQuery = _mesa_check_query;
142
}
143
 
144
 
145
/**
146
 * Return pointer to the query object binding point for the given target.
147
 * \return NULL if invalid target, else the address of binding point
148
 */
149
static struct gl_query_object **
150
get_query_binding_point(struct gl_context *ctx, GLenum target)
151
{
152
   switch (target) {
153
   case GL_SAMPLES_PASSED_ARB:
154
      if (ctx->Extensions.ARB_occlusion_query)
155
         return &ctx->Query.CurrentOcclusionObject;
156
      else
157
         return NULL;
158
   case GL_ANY_SAMPLES_PASSED:
159
      if (ctx->Extensions.ARB_occlusion_query2)
160
         return &ctx->Query.CurrentOcclusionObject;
161
      else
162
         return NULL;
163
   case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
164
      if (ctx->Extensions.ARB_ES3_compatibility
165
          || (ctx->API == API_OPENGLES2 && ctx->Version >= 30))
166
         return &ctx->Query.CurrentOcclusionObject;
167
      else
168
         return NULL;
169
   case GL_TIME_ELAPSED_EXT:
170
      if (ctx->Extensions.EXT_timer_query)
171
         return &ctx->Query.CurrentTimerObject;
172
      else
173
         return NULL;
174
   case GL_PRIMITIVES_GENERATED:
175
      if (ctx->Extensions.EXT_transform_feedback)
176
         return &ctx->Query.PrimitivesGenerated;
177
      else
178
         return NULL;
179
   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
180
      if (ctx->Extensions.EXT_transform_feedback)
181
         return &ctx->Query.PrimitivesWritten;
182
      else
183
         return NULL;
184
   default:
185
      return NULL;
186
   }
187
}
188
 
189
 
190
void GLAPIENTRY
191
_mesa_GenQueries(GLsizei n, GLuint *ids)
192
{
193
   GLuint first;
194
   GET_CURRENT_CONTEXT(ctx);
195
 
196
   if (MESA_VERBOSE & VERBOSE_API)
197
      _mesa_debug(ctx, "glGenQueries(%d)\n", n);
198
 
199
   if (n < 0) {
200
      _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)");
201
      return;
202
   }
203
 
204
   first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n);
205
   if (first) {
206
      GLsizei i;
207
      for (i = 0; i < n; i++) {
208
         struct gl_query_object *q
209
            = ctx->Driver.NewQueryObject(ctx, first + i);
210
         if (!q) {
211
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB");
212
            return;
213
         }
214
         ids[i] = first + i;
215
         _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q);
216
      }
217
   }
218
}
219
 
220
 
221
void GLAPIENTRY
222
_mesa_DeleteQueries(GLsizei n, const GLuint *ids)
223
{
224
   GLint i;
225
   GET_CURRENT_CONTEXT(ctx);
226
   FLUSH_VERTICES(ctx, 0);
227
 
228
   if (MESA_VERBOSE & VERBOSE_API)
229
      _mesa_debug(ctx, "glDeleteQueries(%d)\n", n);
230
 
231
   if (n < 0) {
232
      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)");
233
      return;
234
   }
235
 
236
   for (i = 0; i < n; i++) {
237
      if (ids[i] > 0) {
238
         struct gl_query_object *q = _mesa_lookup_query_object(ctx, ids[i]);
239
         if (q) {
4401 Serge 240
            if (q->Active) {
241
               struct gl_query_object **bindpt;
242
               bindpt = get_query_binding_point(ctx, q->Target);
243
               assert(bindpt); /* Should be non-null for active q. */
244
               if (bindpt) {
245
                  *bindpt = NULL;
246
               }
247
               q->Active = GL_FALSE;
248
               ctx->Driver.EndQuery(ctx, q);
249
            }
4358 Serge 250
            _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]);
251
            ctx->Driver.DeleteQuery(ctx, q);
252
         }
253
      }
254
   }
255
}
256
 
257
 
258
GLboolean GLAPIENTRY
259
_mesa_IsQuery(GLuint id)
260
{
261
   struct gl_query_object *q;
262
 
263
   GET_CURRENT_CONTEXT(ctx);
264
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
265
 
266
   if (MESA_VERBOSE & VERBOSE_API)
267
      _mesa_debug(ctx, "glIsQuery(%u)\n", id);
268
 
269
   if (id == 0)
270
      return GL_FALSE;
271
 
272
   q = _mesa_lookup_query_object(ctx, id);
273
   if (q == NULL)
274
      return GL_FALSE;
275
 
276
   return q->EverBound;
277
}
278
 
279
static GLboolean
280
query_error_check_index(struct gl_context *ctx, GLenum target, GLuint index)
281
{
282
   switch (target) {
283
   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
284
   case GL_PRIMITIVES_GENERATED:
285
      if (index >= ctx->Const.MaxVertexStreams) {
286
         _mesa_error(ctx, GL_INVALID_VALUE,
287
                     "glBeginQueryIndexed(index>=MaxVertexStreams)");
288
         return GL_FALSE;
289
      }
290
      break;
291
   default:
292
      if (index > 0) {
293
         _mesa_error(ctx, GL_INVALID_VALUE, "glBeginQueryIndexed(index>0)");
294
         return GL_FALSE;
295
      }
296
   }
297
   return GL_TRUE;
298
}
299
 
300
void GLAPIENTRY
301
_mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id)
302
{
303
   struct gl_query_object *q, **bindpt;
304
   GET_CURRENT_CONTEXT(ctx);
305
 
306
   if (MESA_VERBOSE & VERBOSE_API)
307
      _mesa_debug(ctx, "glBeginQueryIndexed(%s, %u, %u)\n",
308
                  _mesa_lookup_enum_by_nr(target), index, id);
309
 
310
   if (!query_error_check_index(ctx, target, index))
311
      return;
312
 
313
   FLUSH_VERTICES(ctx, 0);
314
 
315
   bindpt = get_query_binding_point(ctx, target);
316
   if (!bindpt) {
317
      _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQuery{Indexed}(target)");
318
      return;
319
   }
320
 
321
   /* From the GL_ARB_occlusion_query spec:
322
    *
323
    *     "If BeginQueryARB is called while another query is already in
324
    *      progress with the same target, an INVALID_OPERATION error is
325
    *      generated."
326
    */
327
   if (*bindpt) {
328
      _mesa_error(ctx, GL_INVALID_OPERATION,
329
                  "glBeginQuery{Indexed}(target=%s is active)",
330
                  _mesa_lookup_enum_by_nr(target));
331
      return;
332
   }
333
 
334
   if (id == 0) {
335
      _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQuery{Indexed}(id==0)");
336
      return;
337
   }
338
 
339
   q = _mesa_lookup_query_object(ctx, id);
340
   if (!q) {
341
      if (ctx->API != API_OPENGL_COMPAT) {
342
         _mesa_error(ctx, GL_INVALID_OPERATION,
343
                     "glBeginQuery{Indexed}(non-gen name)");
344
         return;
345
      } else {
346
         /* create new object */
347
         q = ctx->Driver.NewQueryObject(ctx, id);
348
         if (!q) {
349
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQuery{Indexed}");
350
            return;
351
         }
352
         _mesa_HashInsert(ctx->Query.QueryObjects, id, q);
353
      }
354
   }
355
   else {
356
      /* pre-existing object */
357
      if (q->Active) {
358
         _mesa_error(ctx, GL_INVALID_OPERATION,
359
                     "glBeginQuery{Indexed}(query already active)");
360
         return;
361
      }
362
   }
363
 
364
   q->Target = target;
365
   q->Active = GL_TRUE;
366
   q->Result = 0;
367
   q->Ready = GL_FALSE;
368
   q->EverBound = GL_TRUE;
369
 
370
   /* XXX should probably refcount query objects */
371
   *bindpt = q;
372
 
373
   ctx->Driver.BeginQuery(ctx, q);
374
}
375
 
376
 
377
void GLAPIENTRY
378
_mesa_EndQueryIndexed(GLenum target, GLuint index)
379
{
380
   struct gl_query_object *q, **bindpt;
381
   GET_CURRENT_CONTEXT(ctx);
382
 
383
   if (MESA_VERBOSE & VERBOSE_API)
384
      _mesa_debug(ctx, "glEndQueryIndexed(%s, %u)\n",
385
                  _mesa_lookup_enum_by_nr(target), index);
386
 
387
   if (!query_error_check_index(ctx, target, index))
388
      return;
389
 
390
   FLUSH_VERTICES(ctx, 0);
391
 
392
   bindpt = get_query_binding_point(ctx, target);
393
   if (!bindpt) {
394
      _mesa_error(ctx, GL_INVALID_ENUM, "glEndQuery{Indexed}(target)");
395
      return;
396
   }
397
 
398
   /* XXX should probably refcount query objects */
399
   q = *bindpt;
400
 
401
   /* Check for GL_ANY_SAMPLES_PASSED vs GL_SAMPLES_PASSED. */
402
   if (q && q->Target != target) {
403
      _mesa_error(ctx, GL_INVALID_OPERATION,
404
                  "glEndQuery(target=%s with active query of target %s)",
405
                  _mesa_lookup_enum_by_nr(target),
406
                  _mesa_lookup_enum_by_nr(q->Target));
407
      return;
408
   }
409
 
410
   *bindpt = NULL;
411
 
412
   if (!q || !q->Active) {
413
      _mesa_error(ctx, GL_INVALID_OPERATION,
414
                  "glEndQuery{Indexed}(no matching glBeginQuery{Indexed})");
415
      return;
416
   }
417
 
418
   q->Active = GL_FALSE;
419
   ctx->Driver.EndQuery(ctx, q);
420
}
421
 
422
void GLAPIENTRY
423
_mesa_BeginQuery(GLenum target, GLuint id)
424
{
425
   _mesa_BeginQueryIndexed(target, 0, id);
426
}
427
 
428
void GLAPIENTRY
429
_mesa_EndQuery(GLenum target)
430
{
431
   _mesa_EndQueryIndexed(target, 0);
432
}
433
 
434
void GLAPIENTRY
435
_mesa_QueryCounter(GLuint id, GLenum target)
436
{
437
   struct gl_query_object *q;
438
   GET_CURRENT_CONTEXT(ctx);
439
 
440
   if (MESA_VERBOSE & VERBOSE_API)
441
      _mesa_debug(ctx, "glQueryCounter(%u, %s)\n", id,
442
                  _mesa_lookup_enum_by_nr(target));
443
 
444
   /* error checking */
445
   if (target != GL_TIMESTAMP) {
446
      _mesa_error(ctx, GL_INVALID_ENUM, "glQueryCounter(target)");
447
      return;
448
   }
449
 
450
   if (id == 0) {
451
      _mesa_error(ctx, GL_INVALID_OPERATION, "glQueryCounter(id==0)");
452
      return;
453
   }
454
 
455
   q = _mesa_lookup_query_object(ctx, id);
456
   if (!q) {
457
      /* XXX the Core profile should throw INVALID_OPERATION here */
458
 
459
      /* create new object */
460
      q = ctx->Driver.NewQueryObject(ctx, id);
461
      if (!q) {
462
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glQueryCounter");
463
         return;
464
      }
465
      _mesa_HashInsert(ctx->Query.QueryObjects, id, q);
466
   }
467
   else {
468
      if (q->Target && q->Target != GL_TIMESTAMP) {
469
         _mesa_error(ctx, GL_INVALID_OPERATION,
470
                     "glQueryCounter(id has an invalid target)");
471
         return;
472
      }
473
   }
474
 
475
   if (q->Active) {
476
      _mesa_error(ctx, GL_INVALID_OPERATION, "glQueryCounter(id is active)");
477
      return;
478
   }
479
 
480
   q->Target = target;
481
   q->Result = 0;
482
   q->Ready = GL_FALSE;
483
   q->EverBound = GL_TRUE;
484
 
485
   if (ctx->Driver.QueryCounter) {
486
      ctx->Driver.QueryCounter(ctx, q);
487
   } else {
488
      /* QueryCounter is implemented using EndQuery without BeginQuery
489
       * in drivers. This is actually Direct3D and Gallium convention.
490
       */
491
      ctx->Driver.EndQuery(ctx, q);
492
   }
493
}
494
 
495
 
496
void GLAPIENTRY
497
_mesa_GetQueryIndexediv(GLenum target, GLuint index, GLenum pname,
498
                        GLint *params)
499
{
500
   struct gl_query_object *q = NULL, **bindpt = NULL;
501
   GET_CURRENT_CONTEXT(ctx);
502
 
503
   if (MESA_VERBOSE & VERBOSE_API)
504
      _mesa_debug(ctx, "glGetQueryIndexediv(%s, %u, %s)\n",
505
                  _mesa_lookup_enum_by_nr(target),
506
                  index,
507
                  _mesa_lookup_enum_by_nr(pname));
508
 
509
   if (!query_error_check_index(ctx, target, index))
510
      return;
511
 
512
   if (target == GL_TIMESTAMP) {
513
      if (!ctx->Extensions.ARB_timer_query) {
514
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)");
515
         return;
516
      }
517
   }
518
   else {
519
      bindpt = get_query_binding_point(ctx, target);
520
      if (!bindpt) {
521
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQuery{Indexed}iv(target)");
522
         return;
523
      }
524
 
525
      q = *bindpt;
526
   }
527
 
528
   switch (pname) {
529
      case GL_QUERY_COUNTER_BITS_ARB:
530
         switch (target) {
531
         case GL_SAMPLES_PASSED:
532
            *params = ctx->Const.QueryCounterBits.SamplesPassed;
533
            break;
534
         case GL_ANY_SAMPLES_PASSED:
535
            /* The minimum value of this is 1 if it's nonzero, and the value
536
             * is only ever GL_TRUE or GL_FALSE, so no sense in reporting more
537
             * bits.
538
             */
539
            *params = 1;
540
            break;
541
         case GL_TIME_ELAPSED:
542
            *params = ctx->Const.QueryCounterBits.TimeElapsed;
543
            break;
544
         case GL_TIMESTAMP:
545
            *params = ctx->Const.QueryCounterBits.Timestamp;
546
            break;
547
         case GL_PRIMITIVES_GENERATED:
548
            *params = ctx->Const.QueryCounterBits.PrimitivesGenerated;
549
            break;
550
         case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
551
            *params = ctx->Const.QueryCounterBits.PrimitivesWritten;
552
            break;
553
         default:
554
            _mesa_problem(ctx,
555
                          "Unknown target in glGetQueryIndexediv(target = %s)",
556
                          _mesa_lookup_enum_by_nr(target));
557
            *params = 0;
558
            break;
559
         }
560
         break;
561
      case GL_CURRENT_QUERY_ARB:
562
         *params = (q && q->Target == target) ? q->Id : 0;
563
         break;
564
      default:
565
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQuery{Indexed}iv(pname)");
566
         return;
567
   }
568
}
569
 
570
void GLAPIENTRY
571
_mesa_GetQueryiv(GLenum target, GLenum pname, GLint *params)
572
{
573
   _mesa_GetQueryIndexediv(target, 0, pname, params);
574
}
575
 
576
void GLAPIENTRY
577
_mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params)
578
{
579
   struct gl_query_object *q = NULL;
580
   GET_CURRENT_CONTEXT(ctx);
581
 
582
   if (MESA_VERBOSE & VERBOSE_API)
583
      _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id,
584
                  _mesa_lookup_enum_by_nr(pname));
585
 
586
   if (id)
587
      q = _mesa_lookup_query_object(ctx, id);
588
 
589
   if (!q || q->Active) {
590
      _mesa_error(ctx, GL_INVALID_OPERATION,
591
                  "glGetQueryObjectivARB(id=%d is invalid or active)", id);
592
      return;
593
   }
594
 
595
   switch (pname) {
596
      case GL_QUERY_RESULT_ARB:
597
         if (!q->Ready)
598
            ctx->Driver.WaitQuery(ctx, q);
599
         /* if result is too large for returned type, clamp to max value */
600
         if (q->Target == GL_ANY_SAMPLES_PASSED
601
             || q->Target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) {
602
            if (q->Result)
603
               *params = GL_TRUE;
604
            else
605
               *params = GL_FALSE;
606
         } else {
607
            if (q->Result > 0x7fffffff) {
608
               *params = 0x7fffffff;
609
            }
610
            else {
611
               *params = (GLint)q->Result;
612
            }
613
         }
614
         break;
615
      case GL_QUERY_RESULT_AVAILABLE_ARB:
616
	 if (!q->Ready)
617
	    ctx->Driver.CheckQuery( ctx, q );
618
         *params = q->Ready;
619
         break;
620
      default:
621
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)");
622
         return;
623
   }
624
}
625
 
626
 
627
void GLAPIENTRY
628
_mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
629
{
630
   struct gl_query_object *q = NULL;
631
   GET_CURRENT_CONTEXT(ctx);
632
 
633
   if (MESA_VERBOSE & VERBOSE_API)
634
      _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id,
635
                  _mesa_lookup_enum_by_nr(pname));
636
 
637
   if (id)
638
      q = _mesa_lookup_query_object(ctx, id);
639
 
640
   if (!q || q->Active) {
641
      _mesa_error(ctx, GL_INVALID_OPERATION,
642
                  "glGetQueryObjectuivARB(id=%d is invalid or active)", id);
643
      return;
644
   }
645
 
646
   switch (pname) {
647
      case GL_QUERY_RESULT_ARB:
648
         if (!q->Ready)
649
            ctx->Driver.WaitQuery(ctx, q);
650
         /* if result is too large for returned type, clamp to max value */
651
         if (q->Target == GL_ANY_SAMPLES_PASSED
652
             || q->Target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) {
653
            if (q->Result)
654
               *params = GL_TRUE;
655
            else
656
               *params = GL_FALSE;
657
         } else {
658
            if (q->Result > 0xffffffff) {
659
               *params = 0xffffffff;
660
            }
661
            else {
662
               *params = (GLuint)q->Result;
663
            }
664
         }
665
         break;
666
      case GL_QUERY_RESULT_AVAILABLE_ARB:
667
	 if (!q->Ready)
668
	    ctx->Driver.CheckQuery( ctx, q );
669
         *params = q->Ready;
670
         break;
671
      default:
672
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)");
673
         return;
674
   }
675
}
676
 
677
 
678
/**
679
 * New with GL_EXT_timer_query
680
 */
681
void GLAPIENTRY
682
_mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params)
683
{
684
   struct gl_query_object *q = NULL;
685
   GET_CURRENT_CONTEXT(ctx);
686
 
687
   if (MESA_VERBOSE & VERBOSE_API)
688
      _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id,
689
                  _mesa_lookup_enum_by_nr(pname));
690
 
691
   if (id)
692
      q = _mesa_lookup_query_object(ctx, id);
693
 
694
   if (!q || q->Active) {
695
      _mesa_error(ctx, GL_INVALID_OPERATION,
696
                  "glGetQueryObjectui64vARB(id=%d is invalid or active)", id);
697
      return;
698
   }
699
 
700
   switch (pname) {
701
      case GL_QUERY_RESULT_ARB:
702
         if (!q->Ready)
703
            ctx->Driver.WaitQuery(ctx, q);
704
         *params = q->Result;
705
         break;
706
      case GL_QUERY_RESULT_AVAILABLE_ARB:
707
	 if (!q->Ready)
708
	    ctx->Driver.CheckQuery( ctx, q );
709
         *params = q->Ready;
710
         break;
711
      default:
712
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)");
713
         return;
714
   }
715
}
716
 
717
 
718
/**
719
 * New with GL_EXT_timer_query
720
 */
721
void GLAPIENTRY
722
_mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params)
723
{
724
   struct gl_query_object *q = NULL;
725
   GET_CURRENT_CONTEXT(ctx);
726
 
727
   if (MESA_VERBOSE & VERBOSE_API)
728
      _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id,
729
                  _mesa_lookup_enum_by_nr(pname));
730
 
731
   if (id)
732
      q = _mesa_lookup_query_object(ctx, id);
733
 
734
   if (!q || q->Active) {
735
      _mesa_error(ctx, GL_INVALID_OPERATION,
736
                  "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id);
737
      return;
738
   }
739
 
740
   switch (pname) {
741
      case GL_QUERY_RESULT_ARB:
742
         if (!q->Ready)
743
            ctx->Driver.WaitQuery(ctx, q);
744
         *params = q->Result;
745
         break;
746
      case GL_QUERY_RESULT_AVAILABLE_ARB:
747
	 if (!q->Ready)
748
	    ctx->Driver.CheckQuery( ctx, q );
749
         *params = q->Ready;
750
         break;
751
      default:
752
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)");
753
         return;
754
   }
755
}
756
 
757
/**
758
 * Allocate/init the context state related to query objects.
759
 */
760
void
761
_mesa_init_queryobj(struct gl_context *ctx)
762
{
763
   ctx->Query.QueryObjects = _mesa_NewHashTable();
764
   ctx->Query.CurrentOcclusionObject = NULL;
765
 
766
   ctx->Const.QueryCounterBits.SamplesPassed = 64;
767
   ctx->Const.QueryCounterBits.TimeElapsed = 64;
768
   ctx->Const.QueryCounterBits.Timestamp = 64;
769
   ctx->Const.QueryCounterBits.PrimitivesGenerated = 64;
770
   ctx->Const.QueryCounterBits.PrimitivesWritten = 64;
771
}
772
 
773
 
774
/**
775
 * Callback for deleting a query object.  Called by _mesa_HashDeleteAll().
776
 */
777
static void
778
delete_queryobj_cb(GLuint id, void *data, void *userData)
779
{
780
   struct gl_query_object *q= (struct gl_query_object *) data;
781
   struct gl_context *ctx = (struct gl_context *)userData;
782
   ctx->Driver.DeleteQuery(ctx, q);
783
}
784
 
785
 
786
/**
787
 * Free the context state related to query objects.
788
 */
789
void
790
_mesa_free_queryobj_data(struct gl_context *ctx)
791
{
792
   _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx);
793
   _mesa_DeleteHashTable(ctx->Query.QueryObjects);
794
}