queryobj.c revision c1f859d4
17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
3c1f859d4Smrg * Version:  7.1
47117f1b4Smrg *
5c1f859d4Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
67117f1b4Smrg *
77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
87117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
97117f1b4Smrg * to deal in the Software without restriction, including without limitation
107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
127117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
137117f1b4Smrg *
147117f1b4Smrg * The above copyright notice and this permission notice shall be included
157117f1b4Smrg * in all copies or substantial portions of the Software.
167117f1b4Smrg *
177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
207117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
217117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
227117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
237117f1b4Smrg */
247117f1b4Smrg
257117f1b4Smrg
267117f1b4Smrg#include "glheader.h"
277117f1b4Smrg#include "context.h"
287117f1b4Smrg#include "hash.h"
297117f1b4Smrg#include "imports.h"
307117f1b4Smrg#include "queryobj.h"
317117f1b4Smrg#include "mtypes.h"
327117f1b4Smrg
337117f1b4Smrg
347117f1b4Smrg/**
357117f1b4Smrg * Allocate a new query object.  This is a fallback routine called via
367117f1b4Smrg * ctx->Driver.NewQueryObject().
377117f1b4Smrg * \param ctx - rendering context
387117f1b4Smrg * \param id - the new object's ID
397117f1b4Smrg * \return pointer to new query_object object or NULL if out of memory.
407117f1b4Smrg */
417117f1b4Smrgstruct gl_query_object *
427117f1b4Smrg_mesa_new_query_object(GLcontext *ctx, GLuint id)
437117f1b4Smrg{
447117f1b4Smrg   struct gl_query_object *q = MALLOC_STRUCT(gl_query_object);
457117f1b4Smrg   (void) ctx;
467117f1b4Smrg   if (q) {
477117f1b4Smrg      q->Id = id;
487117f1b4Smrg      q->Result = 0;
497117f1b4Smrg      q->Active = GL_FALSE;
507117f1b4Smrg      q->Ready = GL_TRUE;   /* correct, see spec */
517117f1b4Smrg   }
527117f1b4Smrg   return q;
537117f1b4Smrg}
547117f1b4Smrg
557117f1b4Smrg
567117f1b4Smrg/**
57c1f859d4Smrg * Begin a query.  Software driver fallback.
58c1f859d4Smrg * Called via ctx->Driver.BeginQuery().
59c1f859d4Smrg */
60c1f859d4Smrgvoid
61c1f859d4Smrg_mesa_begin_query(GLcontext *ctx, struct gl_query_object *q)
62c1f859d4Smrg{
63c1f859d4Smrg   /* no-op */
64c1f859d4Smrg}
65c1f859d4Smrg
66c1f859d4Smrg
67c1f859d4Smrg/**
68c1f859d4Smrg * End a query.  Software driver fallback.
69c1f859d4Smrg * Called via ctx->Driver.EndQuery().
70c1f859d4Smrg */
71c1f859d4Smrgvoid
72c1f859d4Smrg_mesa_end_query(GLcontext *ctx, struct gl_query_object *q)
73c1f859d4Smrg{
74c1f859d4Smrg   q->Ready = GL_TRUE;
75c1f859d4Smrg}
76c1f859d4Smrg
77c1f859d4Smrg
78c1f859d4Smrg/**
79c1f859d4Smrg * Wait for query to complete.  Software driver fallback.
80c1f859d4Smrg * Called via ctx->Driver.WaitQuery().
81c1f859d4Smrg */
82c1f859d4Smrgvoid
83c1f859d4Smrg_mesa_wait_query(GLcontext *ctx, struct gl_query_object *q)
84c1f859d4Smrg{
85c1f859d4Smrg   /* For software drivers, _mesa_end_query() should have completed the query.
86c1f859d4Smrg    * For real hardware, implement a proper WaitQuery() driver function.
87c1f859d4Smrg    */
88c1f859d4Smrg   assert(q->Ready);
89c1f859d4Smrg}
90c1f859d4Smrg
91c1f859d4Smrg
92c1f859d4Smrg/**
93c1f859d4Smrg * Delete a query object.  Called via ctx->Driver.DeleteQuery().
947117f1b4Smrg * Not removed from hash table here.
957117f1b4Smrg */
96c1f859d4Smrgvoid
97c1f859d4Smrg_mesa_delete_query(GLcontext *ctx, struct gl_query_object *q)
987117f1b4Smrg{
99c1f859d4Smrg   _mesa_free(q);
1007117f1b4Smrg}
1017117f1b4Smrg
1027117f1b4Smrg
1037117f1b4Smrgstatic struct gl_query_object *
1047117f1b4Smrglookup_query_object(GLcontext *ctx, GLuint id)
1057117f1b4Smrg{
1067117f1b4Smrg   return (struct gl_query_object *)
1077117f1b4Smrg      _mesa_HashLookup(ctx->Query.QueryObjects, id);
1087117f1b4Smrg}
1097117f1b4Smrg
1107117f1b4Smrg
1117117f1b4Smrg
1127117f1b4Smrgvoid GLAPIENTRY
1137117f1b4Smrg_mesa_GenQueriesARB(GLsizei n, GLuint *ids)
1147117f1b4Smrg{
1157117f1b4Smrg   GLuint first;
1167117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1177117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1187117f1b4Smrg
1197117f1b4Smrg   if (n < 0) {
1207117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)");
1217117f1b4Smrg      return;
1227117f1b4Smrg   }
1237117f1b4Smrg
1247117f1b4Smrg   /* No query objects can be active at this time! */
1257117f1b4Smrg   if (ctx->Query.CurrentOcclusionObject ||
1267117f1b4Smrg       ctx->Query.CurrentTimerObject) {
1277117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB");
1287117f1b4Smrg      return;
1297117f1b4Smrg   }
1307117f1b4Smrg
1317117f1b4Smrg   first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n);
1327117f1b4Smrg   if (first) {
1337117f1b4Smrg      GLsizei i;
1347117f1b4Smrg      for (i = 0; i < n; i++) {
1357117f1b4Smrg         struct gl_query_object *q
1367117f1b4Smrg            = ctx->Driver.NewQueryObject(ctx, first + i);
1377117f1b4Smrg         if (!q) {
1387117f1b4Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB");
1397117f1b4Smrg            return;
1407117f1b4Smrg         }
1417117f1b4Smrg         ids[i] = first + i;
1427117f1b4Smrg         _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q);
1437117f1b4Smrg      }
1447117f1b4Smrg   }
1457117f1b4Smrg}
1467117f1b4Smrg
1477117f1b4Smrg
1487117f1b4Smrgvoid GLAPIENTRY
1497117f1b4Smrg_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids)
1507117f1b4Smrg{
1517117f1b4Smrg   GLint i;
1527117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1537117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1547117f1b4Smrg
1557117f1b4Smrg   if (n < 0) {
1567117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)");
1577117f1b4Smrg      return;
1587117f1b4Smrg   }
1597117f1b4Smrg
1607117f1b4Smrg   /* No query objects can be active at this time! */
1617117f1b4Smrg   if (ctx->Query.CurrentOcclusionObject ||
1627117f1b4Smrg       ctx->Query.CurrentTimerObject) {
1637117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB");
1647117f1b4Smrg      return;
1657117f1b4Smrg   }
1667117f1b4Smrg
1677117f1b4Smrg   for (i = 0; i < n; i++) {
1687117f1b4Smrg      if (ids[i] > 0) {
1697117f1b4Smrg         struct gl_query_object *q = lookup_query_object(ctx, ids[i]);
1707117f1b4Smrg         if (q) {
1717117f1b4Smrg            ASSERT(!q->Active); /* should be caught earlier */
1727117f1b4Smrg            _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]);
173c1f859d4Smrg            ctx->Driver.DeleteQuery(ctx, q);
1747117f1b4Smrg         }
1757117f1b4Smrg      }
1767117f1b4Smrg   }
1777117f1b4Smrg}
1787117f1b4Smrg
1797117f1b4Smrg
1807117f1b4SmrgGLboolean GLAPIENTRY
1817117f1b4Smrg_mesa_IsQueryARB(GLuint id)
1827117f1b4Smrg{
1837117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1847117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1857117f1b4Smrg
1867117f1b4Smrg   if (id && lookup_query_object(ctx, id))
1877117f1b4Smrg      return GL_TRUE;
1887117f1b4Smrg   else
1897117f1b4Smrg      return GL_FALSE;
1907117f1b4Smrg}
1917117f1b4Smrg
1927117f1b4Smrg
1937117f1b4Smrgvoid GLAPIENTRY
1947117f1b4Smrg_mesa_BeginQueryARB(GLenum target, GLuint id)
1957117f1b4Smrg{
1967117f1b4Smrg   struct gl_query_object *q;
1977117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1987117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1997117f1b4Smrg
2007117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_DEPTH);
2017117f1b4Smrg
2027117f1b4Smrg   switch (target) {
2037117f1b4Smrg      case GL_SAMPLES_PASSED_ARB:
2047117f1b4Smrg         if (!ctx->Extensions.ARB_occlusion_query) {
2057117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
2067117f1b4Smrg            return;
2077117f1b4Smrg         }
2087117f1b4Smrg         if (ctx->Query.CurrentOcclusionObject) {
2097117f1b4Smrg            _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB");
2107117f1b4Smrg            return;
2117117f1b4Smrg         }
2127117f1b4Smrg         break;
2137117f1b4Smrg#if FEATURE_EXT_timer_query
2147117f1b4Smrg      case GL_TIME_ELAPSED_EXT:
2157117f1b4Smrg         if (!ctx->Extensions.EXT_timer_query) {
2167117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
2177117f1b4Smrg            return;
2187117f1b4Smrg         }
2197117f1b4Smrg         if (ctx->Query.CurrentTimerObject) {
2207117f1b4Smrg            _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB");
2217117f1b4Smrg            return;
2227117f1b4Smrg         }
2237117f1b4Smrg         break;
2247117f1b4Smrg#endif
2257117f1b4Smrg      default:
2267117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
2277117f1b4Smrg         return;
2287117f1b4Smrg   }
2297117f1b4Smrg
2307117f1b4Smrg   if (id == 0) {
2317117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)");
2327117f1b4Smrg      return;
2337117f1b4Smrg   }
2347117f1b4Smrg
2357117f1b4Smrg   q = lookup_query_object(ctx, id);
2367117f1b4Smrg   if (!q) {
2377117f1b4Smrg      /* create new object */
2387117f1b4Smrg      q = ctx->Driver.NewQueryObject(ctx, id);
2397117f1b4Smrg      if (!q) {
2407117f1b4Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB");
2417117f1b4Smrg         return;
2427117f1b4Smrg      }
2437117f1b4Smrg      _mesa_HashInsert(ctx->Query.QueryObjects, id, q);
2447117f1b4Smrg   }
2457117f1b4Smrg   else {
2467117f1b4Smrg      /* pre-existing object */
2477117f1b4Smrg      if (q->Active) {
2487117f1b4Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
2497117f1b4Smrg                     "glBeginQueryARB(query already active)");
2507117f1b4Smrg         return;
2517117f1b4Smrg      }
2527117f1b4Smrg   }
2537117f1b4Smrg
254c1f859d4Smrg   q->Target = target;
2557117f1b4Smrg   q->Active = GL_TRUE;
2567117f1b4Smrg   q->Result = 0;
2577117f1b4Smrg   q->Ready = GL_FALSE;
2587117f1b4Smrg
2597117f1b4Smrg   if (target == GL_SAMPLES_PASSED_ARB) {
2607117f1b4Smrg      ctx->Query.CurrentOcclusionObject = q;
2617117f1b4Smrg   }
2627117f1b4Smrg#if FEATURE_EXT_timer_query
2637117f1b4Smrg   else if (target == GL_TIME_ELAPSED_EXT) {
2647117f1b4Smrg      ctx->Query.CurrentTimerObject = q;
2657117f1b4Smrg   }
2667117f1b4Smrg#endif
2677117f1b4Smrg
268c1f859d4Smrg   ctx->Driver.BeginQuery(ctx, q);
2697117f1b4Smrg}
2707117f1b4Smrg
2717117f1b4Smrg
2727117f1b4Smrgvoid GLAPIENTRY
2737117f1b4Smrg_mesa_EndQueryARB(GLenum target)
2747117f1b4Smrg{
2757117f1b4Smrg   struct gl_query_object *q;
2767117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2777117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
2787117f1b4Smrg
2797117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_DEPTH);
2807117f1b4Smrg
2817117f1b4Smrg   switch (target) {
2827117f1b4Smrg      case GL_SAMPLES_PASSED_ARB:
2837117f1b4Smrg         if (!ctx->Extensions.ARB_occlusion_query) {
2847117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
2857117f1b4Smrg            return;
2867117f1b4Smrg         }
2877117f1b4Smrg         q = ctx->Query.CurrentOcclusionObject;
2887117f1b4Smrg         ctx->Query.CurrentOcclusionObject = NULL;
2897117f1b4Smrg         break;
2907117f1b4Smrg#if FEATURE_EXT_timer_query
2917117f1b4Smrg      case GL_TIME_ELAPSED_EXT:
2927117f1b4Smrg         if (!ctx->Extensions.EXT_timer_query) {
2937117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
2947117f1b4Smrg            return;
2957117f1b4Smrg         }
2967117f1b4Smrg         q = ctx->Query.CurrentTimerObject;
2977117f1b4Smrg         ctx->Query.CurrentTimerObject = NULL;
2987117f1b4Smrg         break;
2997117f1b4Smrg#endif
3007117f1b4Smrg      default:
3017117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
3027117f1b4Smrg         return;
3037117f1b4Smrg   }
3047117f1b4Smrg
3057117f1b4Smrg   if (!q || !q->Active) {
3067117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3077117f1b4Smrg                  "glEndQueryARB(no matching glBeginQueryARB)");
3087117f1b4Smrg      return;
3097117f1b4Smrg   }
3107117f1b4Smrg
3117117f1b4Smrg   q->Active = GL_FALSE;
312c1f859d4Smrg   ctx->Driver.EndQuery(ctx, q);
3137117f1b4Smrg}
3147117f1b4Smrg
3157117f1b4Smrg
3167117f1b4Smrgvoid GLAPIENTRY
3177117f1b4Smrg_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
3187117f1b4Smrg{
3197117f1b4Smrg   struct gl_query_object *q;
3207117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
3217117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
3227117f1b4Smrg
3237117f1b4Smrg   switch (target) {
3247117f1b4Smrg      case GL_SAMPLES_PASSED_ARB:
3257117f1b4Smrg         if (!ctx->Extensions.ARB_occlusion_query) {
3267117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
3277117f1b4Smrg            return;
3287117f1b4Smrg         }
3297117f1b4Smrg         q = ctx->Query.CurrentOcclusionObject;
3307117f1b4Smrg         break;
3317117f1b4Smrg#if FEATURE_EXT_timer_query
3327117f1b4Smrg      case GL_TIME_ELAPSED_EXT:
3337117f1b4Smrg         if (!ctx->Extensions.EXT_timer_query) {
3347117f1b4Smrg            _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
3357117f1b4Smrg            return;
3367117f1b4Smrg         }
3377117f1b4Smrg         q = ctx->Query.CurrentTimerObject;
3387117f1b4Smrg         break;
3397117f1b4Smrg#endif
3407117f1b4Smrg      default:
3417117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)");
3427117f1b4Smrg         return;
3437117f1b4Smrg   }
3447117f1b4Smrg
3457117f1b4Smrg   switch (pname) {
3467117f1b4Smrg      case GL_QUERY_COUNTER_BITS_ARB:
3477117f1b4Smrg         *params = 8 * sizeof(q->Result);
3487117f1b4Smrg         break;
3497117f1b4Smrg      case GL_CURRENT_QUERY_ARB:
3507117f1b4Smrg         *params = q ? q->Id : 0;
3517117f1b4Smrg         break;
3527117f1b4Smrg      default:
3537117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)");
3547117f1b4Smrg         return;
3557117f1b4Smrg   }
3567117f1b4Smrg}
3577117f1b4Smrg
3587117f1b4Smrg
3597117f1b4Smrgvoid GLAPIENTRY
3607117f1b4Smrg_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
3617117f1b4Smrg{
3627117f1b4Smrg   struct gl_query_object *q = NULL;
3637117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
3647117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
3657117f1b4Smrg
3667117f1b4Smrg   if (id)
3677117f1b4Smrg      q = lookup_query_object(ctx, id);
3687117f1b4Smrg
3697117f1b4Smrg   if (!q || q->Active) {
3707117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3717117f1b4Smrg                  "glGetQueryObjectivARB(id=%d is invalid or active)", id);
3727117f1b4Smrg      return;
3737117f1b4Smrg   }
3747117f1b4Smrg
3757117f1b4Smrg   switch (pname) {
3767117f1b4Smrg      case GL_QUERY_RESULT_ARB:
377c1f859d4Smrg         if (!q->Ready)
378c1f859d4Smrg            ctx->Driver.WaitQuery(ctx, q);
3797117f1b4Smrg         /* if result is too large for returned type, clamp to max value */
3807117f1b4Smrg         if (q->Result > 0x7fffffff) {
3817117f1b4Smrg            *params = 0x7fffffff;
3827117f1b4Smrg         }
3837117f1b4Smrg         else {
384c1f859d4Smrg            *params = (GLint)q->Result;
3857117f1b4Smrg         }
3867117f1b4Smrg         break;
3877117f1b4Smrg      case GL_QUERY_RESULT_AVAILABLE_ARB:
388c1f859d4Smrg	 if (!q->Ready)
389c1f859d4Smrg	    ctx->Driver.CheckQuery( ctx, q );
3907117f1b4Smrg         *params = q->Ready;
3917117f1b4Smrg         break;
3927117f1b4Smrg      default:
3937117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)");
3947117f1b4Smrg         return;
3957117f1b4Smrg   }
3967117f1b4Smrg}
3977117f1b4Smrg
3987117f1b4Smrg
3997117f1b4Smrgvoid GLAPIENTRY
4007117f1b4Smrg_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
4017117f1b4Smrg{
4027117f1b4Smrg   struct gl_query_object *q = NULL;
4037117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
4047117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
4057117f1b4Smrg
4067117f1b4Smrg   if (id)
4077117f1b4Smrg      q = lookup_query_object(ctx, id);
4087117f1b4Smrg
4097117f1b4Smrg   if (!q || q->Active) {
4107117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
4117117f1b4Smrg                  "glGetQueryObjectuivARB(id=%d is invalid or active)", id);
4127117f1b4Smrg      return;
4137117f1b4Smrg   }
4147117f1b4Smrg
4157117f1b4Smrg   switch (pname) {
4167117f1b4Smrg      case GL_QUERY_RESULT_ARB:
417c1f859d4Smrg         if (!q->Ready)
418c1f859d4Smrg            ctx->Driver.WaitQuery(ctx, q);
4197117f1b4Smrg         /* if result is too large for returned type, clamp to max value */
4207117f1b4Smrg         if (q->Result > 0xffffffff) {
4217117f1b4Smrg            *params = 0xffffffff;
4227117f1b4Smrg         }
4237117f1b4Smrg         else {
424c1f859d4Smrg            *params = (GLuint)q->Result;
4257117f1b4Smrg         }
4267117f1b4Smrg         break;
4277117f1b4Smrg      case GL_QUERY_RESULT_AVAILABLE_ARB:
428c1f859d4Smrg	 if (!q->Ready)
429c1f859d4Smrg	    ctx->Driver.CheckQuery( ctx, q );
4307117f1b4Smrg         *params = q->Ready;
4317117f1b4Smrg         break;
4327117f1b4Smrg      default:
4337117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)");
4347117f1b4Smrg         return;
4357117f1b4Smrg   }
4367117f1b4Smrg}
4377117f1b4Smrg
4387117f1b4Smrg
4397117f1b4Smrg#if FEATURE_EXT_timer_query
4407117f1b4Smrg
4417117f1b4Smrg/**
4427117f1b4Smrg * New with GL_EXT_timer_query
4437117f1b4Smrg */
4447117f1b4Smrgvoid GLAPIENTRY
4457117f1b4Smrg_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params)
4467117f1b4Smrg{
4477117f1b4Smrg   struct gl_query_object *q = NULL;
4487117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
4497117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
4507117f1b4Smrg
4517117f1b4Smrg   if (id)
4527117f1b4Smrg      q = lookup_query_object(ctx, id);
4537117f1b4Smrg
4547117f1b4Smrg   if (!q || q->Active) {
4557117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
4567117f1b4Smrg                  "glGetQueryObjectui64vARB(id=%d is invalid or active)", id);
4577117f1b4Smrg      return;
4587117f1b4Smrg   }
4597117f1b4Smrg
4607117f1b4Smrg   switch (pname) {
4617117f1b4Smrg      case GL_QUERY_RESULT_ARB:
462c1f859d4Smrg         if (!q->Ready)
463c1f859d4Smrg            ctx->Driver.WaitQuery(ctx, q);
4647117f1b4Smrg         *params = q->Result;
4657117f1b4Smrg         break;
4667117f1b4Smrg      case GL_QUERY_RESULT_AVAILABLE_ARB:
467c1f859d4Smrg	 if (!q->Ready)
468c1f859d4Smrg	    ctx->Driver.CheckQuery( ctx, q );
4697117f1b4Smrg         *params = q->Ready;
4707117f1b4Smrg         break;
4717117f1b4Smrg      default:
4727117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)");
4737117f1b4Smrg         return;
4747117f1b4Smrg   }
4757117f1b4Smrg}
4767117f1b4Smrg
4777117f1b4Smrg
4787117f1b4Smrg/**
4797117f1b4Smrg * New with GL_EXT_timer_query
4807117f1b4Smrg */
4817117f1b4Smrgvoid GLAPIENTRY
4827117f1b4Smrg_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)
4837117f1b4Smrg{
4847117f1b4Smrg   struct gl_query_object *q = NULL;
4857117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
4867117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
4877117f1b4Smrg
4887117f1b4Smrg   if (id)
4897117f1b4Smrg      q = lookup_query_object(ctx, id);
4907117f1b4Smrg
4917117f1b4Smrg   if (!q || q->Active) {
4927117f1b4Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
4937117f1b4Smrg                  "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id);
4947117f1b4Smrg      return;
4957117f1b4Smrg   }
4967117f1b4Smrg
4977117f1b4Smrg   switch (pname) {
4987117f1b4Smrg      case GL_QUERY_RESULT_ARB:
499c1f859d4Smrg         if (!q->Ready)
500c1f859d4Smrg            ctx->Driver.WaitQuery(ctx, q);
5017117f1b4Smrg         *params = q->Result;
5027117f1b4Smrg         break;
5037117f1b4Smrg      case GL_QUERY_RESULT_AVAILABLE_ARB:
504c1f859d4Smrg	 if (!q->Ready)
505c1f859d4Smrg	    ctx->Driver.CheckQuery( ctx, q );
5067117f1b4Smrg         *params = q->Ready;
5077117f1b4Smrg         break;
5087117f1b4Smrg      default:
5097117f1b4Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)");
5107117f1b4Smrg         return;
5117117f1b4Smrg   }
5127117f1b4Smrg}
5137117f1b4Smrg
5147117f1b4Smrg#endif /* FEATURE_EXT_timer_query */
5157117f1b4Smrg
5167117f1b4Smrg
5177117f1b4Smrg/**
5187117f1b4Smrg * Allocate/init the context state related to query objects.
5197117f1b4Smrg */
5207117f1b4Smrgvoid
5217117f1b4Smrg_mesa_init_query(GLcontext *ctx)
5227117f1b4Smrg{
5237117f1b4Smrg#if FEATURE_ARB_occlusion_query
5247117f1b4Smrg   ctx->Query.QueryObjects = _mesa_NewHashTable();
5257117f1b4Smrg   ctx->Query.CurrentOcclusionObject = NULL;
5267117f1b4Smrg#endif
5277117f1b4Smrg}
5287117f1b4Smrg
5297117f1b4Smrg
5307117f1b4Smrg/**
5317117f1b4Smrg * Callback for deleting a query object.  Called by _mesa_HashDeleteAll().
5327117f1b4Smrg */
5337117f1b4Smrgstatic void
5347117f1b4Smrgdelete_queryobj_cb(GLuint id, void *data, void *userData)
5357117f1b4Smrg{
5367117f1b4Smrg   struct gl_query_object *q= (struct gl_query_object *) data;
537c1f859d4Smrg   GLcontext *ctx = (GLcontext *)userData;
538c1f859d4Smrg   ctx->Driver.DeleteQuery(ctx, q);
5397117f1b4Smrg}
5407117f1b4Smrg
5417117f1b4Smrg
5427117f1b4Smrg/**
5437117f1b4Smrg * Free the context state related to query objects.
5447117f1b4Smrg */
5457117f1b4Smrgvoid
5467117f1b4Smrg_mesa_free_query_data(GLcontext *ctx)
5477117f1b4Smrg{
548c1f859d4Smrg   _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx);
5497117f1b4Smrg   _mesa_DeleteHashTable(ctx->Query.QueryObjects);
5507117f1b4Smrg}
551