queryobj.c revision 4a49301e
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" 324a49301eSmrg#include "glapi/dispatch.h" 334a49301eSmrg 344a49301eSmrg 354a49301eSmrg#if FEATURE_queryobj 367117f1b4Smrg 377117f1b4Smrg 387117f1b4Smrg/** 397117f1b4Smrg * Allocate a new query object. This is a fallback routine called via 407117f1b4Smrg * ctx->Driver.NewQueryObject(). 417117f1b4Smrg * \param ctx - rendering context 427117f1b4Smrg * \param id - the new object's ID 437117f1b4Smrg * \return pointer to new query_object object or NULL if out of memory. 447117f1b4Smrg */ 454a49301eSmrgstatic struct gl_query_object * 467117f1b4Smrg_mesa_new_query_object(GLcontext *ctx, GLuint id) 477117f1b4Smrg{ 487117f1b4Smrg struct gl_query_object *q = MALLOC_STRUCT(gl_query_object); 497117f1b4Smrg (void) ctx; 507117f1b4Smrg if (q) { 517117f1b4Smrg q->Id = id; 527117f1b4Smrg q->Result = 0; 537117f1b4Smrg q->Active = GL_FALSE; 547117f1b4Smrg q->Ready = GL_TRUE; /* correct, see spec */ 557117f1b4Smrg } 567117f1b4Smrg return q; 577117f1b4Smrg} 587117f1b4Smrg 597117f1b4Smrg 607117f1b4Smrg/** 61c1f859d4Smrg * Begin a query. Software driver fallback. 62c1f859d4Smrg * Called via ctx->Driver.BeginQuery(). 63c1f859d4Smrg */ 644a49301eSmrgstatic void 65c1f859d4Smrg_mesa_begin_query(GLcontext *ctx, struct gl_query_object *q) 66c1f859d4Smrg{ 67c1f859d4Smrg /* no-op */ 68c1f859d4Smrg} 69c1f859d4Smrg 70c1f859d4Smrg 71c1f859d4Smrg/** 72c1f859d4Smrg * End a query. Software driver fallback. 73c1f859d4Smrg * Called via ctx->Driver.EndQuery(). 74c1f859d4Smrg */ 754a49301eSmrgstatic void 76c1f859d4Smrg_mesa_end_query(GLcontext *ctx, struct gl_query_object *q) 77c1f859d4Smrg{ 78c1f859d4Smrg q->Ready = GL_TRUE; 79c1f859d4Smrg} 80c1f859d4Smrg 81c1f859d4Smrg 82c1f859d4Smrg/** 83c1f859d4Smrg * Wait for query to complete. Software driver fallback. 84c1f859d4Smrg * Called via ctx->Driver.WaitQuery(). 85c1f859d4Smrg */ 864a49301eSmrgstatic void 87c1f859d4Smrg_mesa_wait_query(GLcontext *ctx, struct gl_query_object *q) 88c1f859d4Smrg{ 89c1f859d4Smrg /* For software drivers, _mesa_end_query() should have completed the query. 904a49301eSmrg * For real hardware, implement a proper WaitQuery() driver function, 914a49301eSmrg * which may require issuing a flush. 92c1f859d4Smrg */ 93c1f859d4Smrg assert(q->Ready); 94c1f859d4Smrg} 95c1f859d4Smrg 96c1f859d4Smrg 974a49301eSmrg/** 984a49301eSmrg * Check if a query results are ready. Software driver fallback. 994a49301eSmrg * Called via ctx->Driver.CheckQuery(). 1004a49301eSmrg */ 1014a49301eSmrgstatic void 1024a49301eSmrg_mesa_check_query(GLcontext *ctx, struct gl_query_object *q) 1034a49301eSmrg{ 1044a49301eSmrg /* No-op for sw rendering. 1054a49301eSmrg * HW drivers may need to flush at this time. 1064a49301eSmrg */ 1074a49301eSmrg} 1084a49301eSmrg 1094a49301eSmrg 110c1f859d4Smrg/** 111c1f859d4Smrg * Delete a query object. Called via ctx->Driver.DeleteQuery(). 1127117f1b4Smrg * Not removed from hash table here. 1137117f1b4Smrg */ 1144a49301eSmrgstatic void 115c1f859d4Smrg_mesa_delete_query(GLcontext *ctx, struct gl_query_object *q) 1167117f1b4Smrg{ 117c1f859d4Smrg _mesa_free(q); 1187117f1b4Smrg} 1197117f1b4Smrg 1207117f1b4Smrg 1217117f1b4Smrgstatic struct gl_query_object * 1227117f1b4Smrglookup_query_object(GLcontext *ctx, GLuint id) 1237117f1b4Smrg{ 1247117f1b4Smrg return (struct gl_query_object *) 1257117f1b4Smrg _mesa_HashLookup(ctx->Query.QueryObjects, id); 1267117f1b4Smrg} 1277117f1b4Smrg 1287117f1b4Smrg 1297117f1b4Smrg 1304a49301eSmrgvoid 1314a49301eSmrg_mesa_init_query_object_functions(struct dd_function_table *driver) 1324a49301eSmrg{ 1334a49301eSmrg driver->NewQueryObject = _mesa_new_query_object; 1344a49301eSmrg driver->DeleteQuery = _mesa_delete_query; 1354a49301eSmrg driver->BeginQuery = _mesa_begin_query; 1364a49301eSmrg driver->EndQuery = _mesa_end_query; 1374a49301eSmrg driver->WaitQuery = _mesa_wait_query; 1384a49301eSmrg driver->CheckQuery = _mesa_check_query; 1394a49301eSmrg} 1404a49301eSmrg 1414a49301eSmrg 1427117f1b4Smrgvoid GLAPIENTRY 1437117f1b4Smrg_mesa_GenQueriesARB(GLsizei n, GLuint *ids) 1447117f1b4Smrg{ 1457117f1b4Smrg GLuint first; 1467117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 1477117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1487117f1b4Smrg 1497117f1b4Smrg if (n < 0) { 1507117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); 1517117f1b4Smrg return; 1527117f1b4Smrg } 1537117f1b4Smrg 1547117f1b4Smrg /* No query objects can be active at this time! */ 1557117f1b4Smrg if (ctx->Query.CurrentOcclusionObject || 1567117f1b4Smrg ctx->Query.CurrentTimerObject) { 1577117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); 1587117f1b4Smrg return; 1597117f1b4Smrg } 1607117f1b4Smrg 1617117f1b4Smrg first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n); 1627117f1b4Smrg if (first) { 1637117f1b4Smrg GLsizei i; 1647117f1b4Smrg for (i = 0; i < n; i++) { 1657117f1b4Smrg struct gl_query_object *q 1667117f1b4Smrg = ctx->Driver.NewQueryObject(ctx, first + i); 1677117f1b4Smrg if (!q) { 1687117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); 1697117f1b4Smrg return; 1707117f1b4Smrg } 1717117f1b4Smrg ids[i] = first + i; 1727117f1b4Smrg _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q); 1737117f1b4Smrg } 1747117f1b4Smrg } 1757117f1b4Smrg} 1767117f1b4Smrg 1777117f1b4Smrg 1787117f1b4Smrgvoid GLAPIENTRY 1797117f1b4Smrg_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) 1807117f1b4Smrg{ 1817117f1b4Smrg GLint i; 1827117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 1837117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1847117f1b4Smrg 1857117f1b4Smrg if (n < 0) { 1867117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); 1877117f1b4Smrg return; 1887117f1b4Smrg } 1897117f1b4Smrg 1907117f1b4Smrg /* No query objects can be active at this time! */ 1917117f1b4Smrg if (ctx->Query.CurrentOcclusionObject || 1927117f1b4Smrg ctx->Query.CurrentTimerObject) { 1937117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB"); 1947117f1b4Smrg return; 1957117f1b4Smrg } 1967117f1b4Smrg 1977117f1b4Smrg for (i = 0; i < n; i++) { 1987117f1b4Smrg if (ids[i] > 0) { 1997117f1b4Smrg struct gl_query_object *q = lookup_query_object(ctx, ids[i]); 2007117f1b4Smrg if (q) { 2017117f1b4Smrg ASSERT(!q->Active); /* should be caught earlier */ 2027117f1b4Smrg _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]); 203c1f859d4Smrg ctx->Driver.DeleteQuery(ctx, q); 2047117f1b4Smrg } 2057117f1b4Smrg } 2067117f1b4Smrg } 2077117f1b4Smrg} 2087117f1b4Smrg 2097117f1b4Smrg 2107117f1b4SmrgGLboolean GLAPIENTRY 2117117f1b4Smrg_mesa_IsQueryARB(GLuint id) 2127117f1b4Smrg{ 2137117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 2147117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 2157117f1b4Smrg 2167117f1b4Smrg if (id && lookup_query_object(ctx, id)) 2177117f1b4Smrg return GL_TRUE; 2187117f1b4Smrg else 2197117f1b4Smrg return GL_FALSE; 2207117f1b4Smrg} 2217117f1b4Smrg 2227117f1b4Smrg 2234a49301eSmrgstatic void GLAPIENTRY 2247117f1b4Smrg_mesa_BeginQueryARB(GLenum target, GLuint id) 2257117f1b4Smrg{ 2267117f1b4Smrg struct gl_query_object *q; 2277117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 2287117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 2297117f1b4Smrg 2307117f1b4Smrg FLUSH_VERTICES(ctx, _NEW_DEPTH); 2317117f1b4Smrg 2327117f1b4Smrg switch (target) { 2337117f1b4Smrg case GL_SAMPLES_PASSED_ARB: 2347117f1b4Smrg if (!ctx->Extensions.ARB_occlusion_query) { 2357117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); 2367117f1b4Smrg return; 2377117f1b4Smrg } 2387117f1b4Smrg if (ctx->Query.CurrentOcclusionObject) { 2397117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); 2407117f1b4Smrg return; 2417117f1b4Smrg } 2427117f1b4Smrg break; 2437117f1b4Smrg case GL_TIME_ELAPSED_EXT: 2447117f1b4Smrg if (!ctx->Extensions.EXT_timer_query) { 2457117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); 2467117f1b4Smrg return; 2477117f1b4Smrg } 2487117f1b4Smrg if (ctx->Query.CurrentTimerObject) { 2497117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); 2507117f1b4Smrg return; 2517117f1b4Smrg } 2527117f1b4Smrg break; 2537117f1b4Smrg default: 2547117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); 2557117f1b4Smrg return; 2567117f1b4Smrg } 2577117f1b4Smrg 2587117f1b4Smrg if (id == 0) { 2597117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)"); 2607117f1b4Smrg return; 2617117f1b4Smrg } 2627117f1b4Smrg 2637117f1b4Smrg q = lookup_query_object(ctx, id); 2647117f1b4Smrg if (!q) { 2657117f1b4Smrg /* create new object */ 2667117f1b4Smrg q = ctx->Driver.NewQueryObject(ctx, id); 2677117f1b4Smrg if (!q) { 2687117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB"); 2697117f1b4Smrg return; 2707117f1b4Smrg } 2717117f1b4Smrg _mesa_HashInsert(ctx->Query.QueryObjects, id, q); 2727117f1b4Smrg } 2737117f1b4Smrg else { 2747117f1b4Smrg /* pre-existing object */ 2757117f1b4Smrg if (q->Active) { 2767117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 2777117f1b4Smrg "glBeginQueryARB(query already active)"); 2787117f1b4Smrg return; 2797117f1b4Smrg } 2807117f1b4Smrg } 2817117f1b4Smrg 282c1f859d4Smrg q->Target = target; 2837117f1b4Smrg q->Active = GL_TRUE; 2847117f1b4Smrg q->Result = 0; 2857117f1b4Smrg q->Ready = GL_FALSE; 2867117f1b4Smrg 2877117f1b4Smrg if (target == GL_SAMPLES_PASSED_ARB) { 2887117f1b4Smrg ctx->Query.CurrentOcclusionObject = q; 2897117f1b4Smrg } 2907117f1b4Smrg else if (target == GL_TIME_ELAPSED_EXT) { 2917117f1b4Smrg ctx->Query.CurrentTimerObject = q; 2927117f1b4Smrg } 2937117f1b4Smrg 294c1f859d4Smrg ctx->Driver.BeginQuery(ctx, q); 2957117f1b4Smrg} 2967117f1b4Smrg 2977117f1b4Smrg 2984a49301eSmrgstatic void GLAPIENTRY 2997117f1b4Smrg_mesa_EndQueryARB(GLenum target) 3007117f1b4Smrg{ 3017117f1b4Smrg struct gl_query_object *q; 3027117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 3037117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 3047117f1b4Smrg 3057117f1b4Smrg FLUSH_VERTICES(ctx, _NEW_DEPTH); 3067117f1b4Smrg 3077117f1b4Smrg switch (target) { 3087117f1b4Smrg case GL_SAMPLES_PASSED_ARB: 3097117f1b4Smrg if (!ctx->Extensions.ARB_occlusion_query) { 3107117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); 3117117f1b4Smrg return; 3127117f1b4Smrg } 3137117f1b4Smrg q = ctx->Query.CurrentOcclusionObject; 3147117f1b4Smrg ctx->Query.CurrentOcclusionObject = NULL; 3157117f1b4Smrg break; 3167117f1b4Smrg case GL_TIME_ELAPSED_EXT: 3177117f1b4Smrg if (!ctx->Extensions.EXT_timer_query) { 3187117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); 3197117f1b4Smrg return; 3207117f1b4Smrg } 3217117f1b4Smrg q = ctx->Query.CurrentTimerObject; 3227117f1b4Smrg ctx->Query.CurrentTimerObject = NULL; 3237117f1b4Smrg break; 3247117f1b4Smrg default: 3257117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); 3267117f1b4Smrg return; 3277117f1b4Smrg } 3287117f1b4Smrg 3297117f1b4Smrg if (!q || !q->Active) { 3307117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 3317117f1b4Smrg "glEndQueryARB(no matching glBeginQueryARB)"); 3327117f1b4Smrg return; 3337117f1b4Smrg } 3347117f1b4Smrg 3357117f1b4Smrg q->Active = GL_FALSE; 336c1f859d4Smrg ctx->Driver.EndQuery(ctx, q); 3377117f1b4Smrg} 3387117f1b4Smrg 3397117f1b4Smrg 3407117f1b4Smrgvoid GLAPIENTRY 3417117f1b4Smrg_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) 3427117f1b4Smrg{ 3437117f1b4Smrg struct gl_query_object *q; 3447117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 3457117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 3467117f1b4Smrg 3477117f1b4Smrg switch (target) { 3487117f1b4Smrg case GL_SAMPLES_PASSED_ARB: 3497117f1b4Smrg if (!ctx->Extensions.ARB_occlusion_query) { 3507117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); 3517117f1b4Smrg return; 3527117f1b4Smrg } 3537117f1b4Smrg q = ctx->Query.CurrentOcclusionObject; 3547117f1b4Smrg break; 3557117f1b4Smrg case GL_TIME_ELAPSED_EXT: 3567117f1b4Smrg if (!ctx->Extensions.EXT_timer_query) { 3577117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); 3587117f1b4Smrg return; 3597117f1b4Smrg } 3607117f1b4Smrg q = ctx->Query.CurrentTimerObject; 3617117f1b4Smrg break; 3627117f1b4Smrg default: 3637117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)"); 3647117f1b4Smrg return; 3657117f1b4Smrg } 3667117f1b4Smrg 3677117f1b4Smrg switch (pname) { 3687117f1b4Smrg case GL_QUERY_COUNTER_BITS_ARB: 3697117f1b4Smrg *params = 8 * sizeof(q->Result); 3707117f1b4Smrg break; 3717117f1b4Smrg case GL_CURRENT_QUERY_ARB: 3727117f1b4Smrg *params = q ? q->Id : 0; 3737117f1b4Smrg break; 3747117f1b4Smrg default: 3757117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)"); 3767117f1b4Smrg return; 3777117f1b4Smrg } 3787117f1b4Smrg} 3797117f1b4Smrg 3807117f1b4Smrg 3817117f1b4Smrgvoid GLAPIENTRY 3827117f1b4Smrg_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) 3837117f1b4Smrg{ 3847117f1b4Smrg struct gl_query_object *q = NULL; 3857117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 3867117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 3877117f1b4Smrg 3887117f1b4Smrg if (id) 3897117f1b4Smrg q = lookup_query_object(ctx, id); 3907117f1b4Smrg 3917117f1b4Smrg if (!q || q->Active) { 3927117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 3937117f1b4Smrg "glGetQueryObjectivARB(id=%d is invalid or active)", id); 3947117f1b4Smrg return; 3957117f1b4Smrg } 3967117f1b4Smrg 3977117f1b4Smrg switch (pname) { 3987117f1b4Smrg case GL_QUERY_RESULT_ARB: 399c1f859d4Smrg if (!q->Ready) 400c1f859d4Smrg ctx->Driver.WaitQuery(ctx, q); 4017117f1b4Smrg /* if result is too large for returned type, clamp to max value */ 4027117f1b4Smrg if (q->Result > 0x7fffffff) { 4037117f1b4Smrg *params = 0x7fffffff; 4047117f1b4Smrg } 4057117f1b4Smrg else { 406c1f859d4Smrg *params = (GLint)q->Result; 4077117f1b4Smrg } 4087117f1b4Smrg break; 4097117f1b4Smrg case GL_QUERY_RESULT_AVAILABLE_ARB: 410c1f859d4Smrg if (!q->Ready) 411c1f859d4Smrg ctx->Driver.CheckQuery( ctx, q ); 4127117f1b4Smrg *params = q->Ready; 4137117f1b4Smrg break; 4147117f1b4Smrg default: 4157117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)"); 4167117f1b4Smrg return; 4177117f1b4Smrg } 4187117f1b4Smrg} 4197117f1b4Smrg 4207117f1b4Smrg 4217117f1b4Smrgvoid GLAPIENTRY 4227117f1b4Smrg_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) 4237117f1b4Smrg{ 4247117f1b4Smrg struct gl_query_object *q = NULL; 4257117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 4267117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 4277117f1b4Smrg 4287117f1b4Smrg if (id) 4297117f1b4Smrg q = lookup_query_object(ctx, id); 4307117f1b4Smrg 4317117f1b4Smrg if (!q || q->Active) { 4327117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 4337117f1b4Smrg "glGetQueryObjectuivARB(id=%d is invalid or active)", id); 4347117f1b4Smrg return; 4357117f1b4Smrg } 4367117f1b4Smrg 4377117f1b4Smrg switch (pname) { 4387117f1b4Smrg case GL_QUERY_RESULT_ARB: 439c1f859d4Smrg if (!q->Ready) 440c1f859d4Smrg ctx->Driver.WaitQuery(ctx, q); 4417117f1b4Smrg /* if result is too large for returned type, clamp to max value */ 4427117f1b4Smrg if (q->Result > 0xffffffff) { 4437117f1b4Smrg *params = 0xffffffff; 4447117f1b4Smrg } 4457117f1b4Smrg else { 446c1f859d4Smrg *params = (GLuint)q->Result; 4477117f1b4Smrg } 4487117f1b4Smrg break; 4497117f1b4Smrg case GL_QUERY_RESULT_AVAILABLE_ARB: 450c1f859d4Smrg if (!q->Ready) 451c1f859d4Smrg ctx->Driver.CheckQuery( ctx, q ); 4527117f1b4Smrg *params = q->Ready; 4537117f1b4Smrg break; 4547117f1b4Smrg default: 4557117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); 4567117f1b4Smrg return; 4577117f1b4Smrg } 4587117f1b4Smrg} 4597117f1b4Smrg 4607117f1b4Smrg 4617117f1b4Smrg/** 4627117f1b4Smrg * New with GL_EXT_timer_query 4637117f1b4Smrg */ 4644a49301eSmrgstatic void GLAPIENTRY 4657117f1b4Smrg_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) 4667117f1b4Smrg{ 4677117f1b4Smrg struct gl_query_object *q = NULL; 4687117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 4697117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 4707117f1b4Smrg 4717117f1b4Smrg if (id) 4727117f1b4Smrg q = lookup_query_object(ctx, id); 4737117f1b4Smrg 4747117f1b4Smrg if (!q || q->Active) { 4757117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 4767117f1b4Smrg "glGetQueryObjectui64vARB(id=%d is invalid or active)", id); 4777117f1b4Smrg return; 4787117f1b4Smrg } 4797117f1b4Smrg 4807117f1b4Smrg switch (pname) { 4817117f1b4Smrg case GL_QUERY_RESULT_ARB: 482c1f859d4Smrg if (!q->Ready) 483c1f859d4Smrg ctx->Driver.WaitQuery(ctx, q); 4847117f1b4Smrg *params = q->Result; 4857117f1b4Smrg break; 4867117f1b4Smrg case GL_QUERY_RESULT_AVAILABLE_ARB: 487c1f859d4Smrg if (!q->Ready) 488c1f859d4Smrg ctx->Driver.CheckQuery( ctx, q ); 4897117f1b4Smrg *params = q->Ready; 4907117f1b4Smrg break; 4917117f1b4Smrg default: 4927117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)"); 4937117f1b4Smrg return; 4947117f1b4Smrg } 4957117f1b4Smrg} 4967117f1b4Smrg 4977117f1b4Smrg 4987117f1b4Smrg/** 4997117f1b4Smrg * New with GL_EXT_timer_query 5007117f1b4Smrg */ 5014a49301eSmrgstatic void GLAPIENTRY 5027117f1b4Smrg_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) 5037117f1b4Smrg{ 5047117f1b4Smrg struct gl_query_object *q = NULL; 5057117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 5067117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 5077117f1b4Smrg 5087117f1b4Smrg if (id) 5097117f1b4Smrg q = lookup_query_object(ctx, id); 5107117f1b4Smrg 5117117f1b4Smrg if (!q || q->Active) { 5127117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 5137117f1b4Smrg "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id); 5147117f1b4Smrg return; 5157117f1b4Smrg } 5167117f1b4Smrg 5177117f1b4Smrg switch (pname) { 5187117f1b4Smrg case GL_QUERY_RESULT_ARB: 519c1f859d4Smrg if (!q->Ready) 520c1f859d4Smrg ctx->Driver.WaitQuery(ctx, q); 5217117f1b4Smrg *params = q->Result; 5227117f1b4Smrg break; 5237117f1b4Smrg case GL_QUERY_RESULT_AVAILABLE_ARB: 524c1f859d4Smrg if (!q->Ready) 525c1f859d4Smrg ctx->Driver.CheckQuery( ctx, q ); 5267117f1b4Smrg *params = q->Ready; 5277117f1b4Smrg break; 5287117f1b4Smrg default: 5297117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)"); 5307117f1b4Smrg return; 5317117f1b4Smrg } 5327117f1b4Smrg} 5337117f1b4Smrg 5344a49301eSmrg 5354a49301eSmrgvoid 5364a49301eSmrg_mesa_init_queryobj_dispatch(struct _glapi_table *disp) 5374a49301eSmrg{ 5384a49301eSmrg SET_GenQueriesARB(disp, _mesa_GenQueriesARB); 5394a49301eSmrg SET_DeleteQueriesARB(disp, _mesa_DeleteQueriesARB); 5404a49301eSmrg SET_IsQueryARB(disp, _mesa_IsQueryARB); 5414a49301eSmrg SET_BeginQueryARB(disp, _mesa_BeginQueryARB); 5424a49301eSmrg SET_EndQueryARB(disp, _mesa_EndQueryARB); 5434a49301eSmrg SET_GetQueryivARB(disp, _mesa_GetQueryivARB); 5444a49301eSmrg SET_GetQueryObjectivARB(disp, _mesa_GetQueryObjectivARB); 5454a49301eSmrg SET_GetQueryObjectuivARB(disp, _mesa_GetQueryObjectuivARB); 5464a49301eSmrg 5474a49301eSmrg SET_GetQueryObjecti64vEXT(disp, _mesa_GetQueryObjecti64vEXT); 5484a49301eSmrg SET_GetQueryObjectui64vEXT(disp, _mesa_GetQueryObjectui64vEXT); 5494a49301eSmrg} 5504a49301eSmrg 5514a49301eSmrg 5524a49301eSmrg#endif /* FEATURE_queryobj */ 5537117f1b4Smrg 5547117f1b4Smrg 5557117f1b4Smrg/** 5567117f1b4Smrg * Allocate/init the context state related to query objects. 5577117f1b4Smrg */ 5587117f1b4Smrgvoid 5594a49301eSmrg_mesa_init_queryobj(GLcontext *ctx) 5607117f1b4Smrg{ 5617117f1b4Smrg ctx->Query.QueryObjects = _mesa_NewHashTable(); 5627117f1b4Smrg ctx->Query.CurrentOcclusionObject = NULL; 5637117f1b4Smrg} 5647117f1b4Smrg 5657117f1b4Smrg 5667117f1b4Smrg/** 5677117f1b4Smrg * Callback for deleting a query object. Called by _mesa_HashDeleteAll(). 5687117f1b4Smrg */ 5697117f1b4Smrgstatic void 5707117f1b4Smrgdelete_queryobj_cb(GLuint id, void *data, void *userData) 5717117f1b4Smrg{ 5727117f1b4Smrg struct gl_query_object *q= (struct gl_query_object *) data; 573c1f859d4Smrg GLcontext *ctx = (GLcontext *)userData; 574c1f859d4Smrg ctx->Driver.DeleteQuery(ctx, q); 5757117f1b4Smrg} 5767117f1b4Smrg 5777117f1b4Smrg 5787117f1b4Smrg/** 5797117f1b4Smrg * Free the context state related to query objects. 5807117f1b4Smrg */ 5817117f1b4Smrgvoid 5824a49301eSmrg_mesa_free_queryobj_data(GLcontext *ctx) 5837117f1b4Smrg{ 584c1f859d4Smrg _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx); 5857117f1b4Smrg _mesa_DeleteHashTable(ctx->Query.QueryObjects); 5867117f1b4Smrg} 587