queryobj.c revision 3464ebd5
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" 283464ebd5Sriastradh#include "enums.h" 297117f1b4Smrg#include "hash.h" 307117f1b4Smrg#include "imports.h" 317117f1b4Smrg#include "queryobj.h" 323464ebd5Sriastradh#include "mfeatures.h" 337117f1b4Smrg#include "mtypes.h" 34cdc920a0Smrg#include "main/dispatch.h" 354a49301eSmrg 364a49301eSmrg 374a49301eSmrg#if FEATURE_queryobj 387117f1b4Smrg 397117f1b4Smrg 407117f1b4Smrg/** 417117f1b4Smrg * Allocate a new query object. This is a fallback routine called via 427117f1b4Smrg * ctx->Driver.NewQueryObject(). 437117f1b4Smrg * \param ctx - rendering context 447117f1b4Smrg * \param id - the new object's ID 457117f1b4Smrg * \return pointer to new query_object object or NULL if out of memory. 467117f1b4Smrg */ 474a49301eSmrgstatic struct gl_query_object * 483464ebd5Sriastradh_mesa_new_query_object(struct gl_context *ctx, GLuint id) 497117f1b4Smrg{ 507117f1b4Smrg struct gl_query_object *q = MALLOC_STRUCT(gl_query_object); 517117f1b4Smrg (void) ctx; 527117f1b4Smrg if (q) { 537117f1b4Smrg q->Id = id; 547117f1b4Smrg q->Result = 0; 557117f1b4Smrg q->Active = GL_FALSE; 567117f1b4Smrg q->Ready = GL_TRUE; /* correct, see spec */ 577117f1b4Smrg } 587117f1b4Smrg return q; 597117f1b4Smrg} 607117f1b4Smrg 617117f1b4Smrg 627117f1b4Smrg/** 63c1f859d4Smrg * Begin a query. Software driver fallback. 64c1f859d4Smrg * Called via ctx->Driver.BeginQuery(). 65c1f859d4Smrg */ 664a49301eSmrgstatic void 673464ebd5Sriastradh_mesa_begin_query(struct gl_context *ctx, struct gl_query_object *q) 68c1f859d4Smrg{ 69c1f859d4Smrg /* no-op */ 70c1f859d4Smrg} 71c1f859d4Smrg 72c1f859d4Smrg 73c1f859d4Smrg/** 74c1f859d4Smrg * End a query. Software driver fallback. 75c1f859d4Smrg * Called via ctx->Driver.EndQuery(). 76c1f859d4Smrg */ 774a49301eSmrgstatic void 783464ebd5Sriastradh_mesa_end_query(struct gl_context *ctx, struct gl_query_object *q) 79c1f859d4Smrg{ 80c1f859d4Smrg q->Ready = GL_TRUE; 81c1f859d4Smrg} 82c1f859d4Smrg 83c1f859d4Smrg 84c1f859d4Smrg/** 85c1f859d4Smrg * Wait for query to complete. Software driver fallback. 86c1f859d4Smrg * Called via ctx->Driver.WaitQuery(). 87c1f859d4Smrg */ 884a49301eSmrgstatic void 893464ebd5Sriastradh_mesa_wait_query(struct gl_context *ctx, struct gl_query_object *q) 90c1f859d4Smrg{ 91c1f859d4Smrg /* For software drivers, _mesa_end_query() should have completed the query. 924a49301eSmrg * For real hardware, implement a proper WaitQuery() driver function, 934a49301eSmrg * which may require issuing a flush. 94c1f859d4Smrg */ 95c1f859d4Smrg assert(q->Ready); 96c1f859d4Smrg} 97c1f859d4Smrg 98c1f859d4Smrg 994a49301eSmrg/** 1004a49301eSmrg * Check if a query results are ready. Software driver fallback. 1014a49301eSmrg * Called via ctx->Driver.CheckQuery(). 1024a49301eSmrg */ 1034a49301eSmrgstatic void 1043464ebd5Sriastradh_mesa_check_query(struct gl_context *ctx, struct gl_query_object *q) 1054a49301eSmrg{ 1064a49301eSmrg /* No-op for sw rendering. 1074a49301eSmrg * HW drivers may need to flush at this time. 1084a49301eSmrg */ 1094a49301eSmrg} 1104a49301eSmrg 1114a49301eSmrg 112c1f859d4Smrg/** 113c1f859d4Smrg * Delete a query object. Called via ctx->Driver.DeleteQuery(). 1147117f1b4Smrg * Not removed from hash table here. 1157117f1b4Smrg */ 1164a49301eSmrgstatic void 1173464ebd5Sriastradh_mesa_delete_query(struct gl_context *ctx, struct gl_query_object *q) 1187117f1b4Smrg{ 119cdc920a0Smrg free(q); 1207117f1b4Smrg} 1217117f1b4Smrg 1227117f1b4Smrg 1234a49301eSmrgvoid 1244a49301eSmrg_mesa_init_query_object_functions(struct dd_function_table *driver) 1254a49301eSmrg{ 1264a49301eSmrg driver->NewQueryObject = _mesa_new_query_object; 1274a49301eSmrg driver->DeleteQuery = _mesa_delete_query; 1284a49301eSmrg driver->BeginQuery = _mesa_begin_query; 1294a49301eSmrg driver->EndQuery = _mesa_end_query; 1304a49301eSmrg driver->WaitQuery = _mesa_wait_query; 1314a49301eSmrg driver->CheckQuery = _mesa_check_query; 1324a49301eSmrg} 1334a49301eSmrg 1344a49301eSmrg 1353464ebd5Sriastradh/** 1363464ebd5Sriastradh * Return pointer to the query object binding point for the given target. 1373464ebd5Sriastradh * \return NULL if invalid target, else the address of binding point 1383464ebd5Sriastradh */ 1393464ebd5Sriastradhstatic struct gl_query_object ** 1403464ebd5Sriastradhget_query_binding_point(struct gl_context *ctx, GLenum target) 1413464ebd5Sriastradh{ 1423464ebd5Sriastradh switch (target) { 1433464ebd5Sriastradh case GL_SAMPLES_PASSED_ARB: 1443464ebd5Sriastradh if (ctx->Extensions.ARB_occlusion_query) 1453464ebd5Sriastradh return &ctx->Query.CurrentOcclusionObject; 1463464ebd5Sriastradh else 1473464ebd5Sriastradh return NULL; 1483464ebd5Sriastradh case GL_ANY_SAMPLES_PASSED: 1493464ebd5Sriastradh if (ctx->Extensions.ARB_occlusion_query2) 1503464ebd5Sriastradh return &ctx->Query.CurrentOcclusionObject; 1513464ebd5Sriastradh else 1523464ebd5Sriastradh return NULL; 1533464ebd5Sriastradh case GL_TIME_ELAPSED_EXT: 1543464ebd5Sriastradh if (ctx->Extensions.EXT_timer_query) 1553464ebd5Sriastradh return &ctx->Query.CurrentTimerObject; 1563464ebd5Sriastradh else 1573464ebd5Sriastradh return NULL; 1583464ebd5Sriastradh#if FEATURE_EXT_transform_feedback 1593464ebd5Sriastradh case GL_PRIMITIVES_GENERATED: 1603464ebd5Sriastradh if (ctx->Extensions.EXT_transform_feedback) 1613464ebd5Sriastradh return &ctx->Query.PrimitivesGenerated; 1623464ebd5Sriastradh else 1633464ebd5Sriastradh return NULL; 1643464ebd5Sriastradh case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: 1653464ebd5Sriastradh if (ctx->Extensions.EXT_transform_feedback) 1663464ebd5Sriastradh return &ctx->Query.PrimitivesWritten; 1673464ebd5Sriastradh else 1683464ebd5Sriastradh return NULL; 1693464ebd5Sriastradh#endif 1703464ebd5Sriastradh default: 1713464ebd5Sriastradh return NULL; 1723464ebd5Sriastradh } 1733464ebd5Sriastradh} 1743464ebd5Sriastradh 1753464ebd5Sriastradh 1763464ebd5Sriastradhstatic void GLAPIENTRY 1777117f1b4Smrg_mesa_GenQueriesARB(GLsizei n, GLuint *ids) 1787117f1b4Smrg{ 1797117f1b4Smrg GLuint first; 1807117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 1817117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1827117f1b4Smrg 1833464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 1843464ebd5Sriastradh _mesa_debug(ctx, "glGenQueries(%d)\n", n); 1853464ebd5Sriastradh 1867117f1b4Smrg if (n < 0) { 1877117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); 1887117f1b4Smrg return; 1897117f1b4Smrg } 1907117f1b4Smrg 1917117f1b4Smrg /* No query objects can be active at this time! */ 1927117f1b4Smrg if (ctx->Query.CurrentOcclusionObject || 1937117f1b4Smrg ctx->Query.CurrentTimerObject) { 1947117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); 1957117f1b4Smrg return; 1967117f1b4Smrg } 1977117f1b4Smrg 1987117f1b4Smrg first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n); 1997117f1b4Smrg if (first) { 2007117f1b4Smrg GLsizei i; 2017117f1b4Smrg for (i = 0; i < n; i++) { 2027117f1b4Smrg struct gl_query_object *q 2037117f1b4Smrg = ctx->Driver.NewQueryObject(ctx, first + i); 2047117f1b4Smrg if (!q) { 2057117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); 2067117f1b4Smrg return; 2077117f1b4Smrg } 2087117f1b4Smrg ids[i] = first + i; 2097117f1b4Smrg _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q); 2107117f1b4Smrg } 2117117f1b4Smrg } 2127117f1b4Smrg} 2137117f1b4Smrg 2147117f1b4Smrg 2153464ebd5Sriastradhstatic void GLAPIENTRY 2167117f1b4Smrg_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) 2177117f1b4Smrg{ 2187117f1b4Smrg GLint i; 2197117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 2207117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 2213464ebd5Sriastradh FLUSH_VERTICES(ctx, 0); 2223464ebd5Sriastradh 2233464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 2243464ebd5Sriastradh _mesa_debug(ctx, "glDeleeteQueries(%d)\n", n); 2257117f1b4Smrg 2267117f1b4Smrg if (n < 0) { 2277117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); 2287117f1b4Smrg return; 2297117f1b4Smrg } 2307117f1b4Smrg 2317117f1b4Smrg /* No query objects can be active at this time! */ 2327117f1b4Smrg if (ctx->Query.CurrentOcclusionObject || 2337117f1b4Smrg ctx->Query.CurrentTimerObject) { 2347117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB"); 2357117f1b4Smrg return; 2367117f1b4Smrg } 2377117f1b4Smrg 2387117f1b4Smrg for (i = 0; i < n; i++) { 2397117f1b4Smrg if (ids[i] > 0) { 240cdc920a0Smrg struct gl_query_object *q = _mesa_lookup_query_object(ctx, ids[i]); 2417117f1b4Smrg if (q) { 2427117f1b4Smrg ASSERT(!q->Active); /* should be caught earlier */ 2437117f1b4Smrg _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]); 244c1f859d4Smrg ctx->Driver.DeleteQuery(ctx, q); 2457117f1b4Smrg } 2467117f1b4Smrg } 2477117f1b4Smrg } 2487117f1b4Smrg} 2497117f1b4Smrg 2507117f1b4Smrg 2513464ebd5Sriastradhstatic GLboolean GLAPIENTRY 2527117f1b4Smrg_mesa_IsQueryARB(GLuint id) 2537117f1b4Smrg{ 2547117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 2557117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 2567117f1b4Smrg 2573464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 2583464ebd5Sriastradh _mesa_debug(ctx, "glIsQuery(%u)\n", id); 2593464ebd5Sriastradh 260cdc920a0Smrg if (id && _mesa_lookup_query_object(ctx, id)) 2617117f1b4Smrg return GL_TRUE; 2627117f1b4Smrg else 2637117f1b4Smrg return GL_FALSE; 2647117f1b4Smrg} 2657117f1b4Smrg 2667117f1b4Smrg 2674a49301eSmrgstatic void GLAPIENTRY 2687117f1b4Smrg_mesa_BeginQueryARB(GLenum target, GLuint id) 2697117f1b4Smrg{ 2703464ebd5Sriastradh struct gl_query_object *q, **bindpt; 2717117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 2727117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 2737117f1b4Smrg 2743464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 2753464ebd5Sriastradh _mesa_debug(ctx, "glBeginQuery(%s, %u)\n", 2763464ebd5Sriastradh _mesa_lookup_enum_by_nr(target), id); 2773464ebd5Sriastradh 2787117f1b4Smrg FLUSH_VERTICES(ctx, _NEW_DEPTH); 2797117f1b4Smrg 2803464ebd5Sriastradh bindpt = get_query_binding_point(ctx, target); 2813464ebd5Sriastradh if (!bindpt) { 2823464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); 2833464ebd5Sriastradh return; 2847117f1b4Smrg } 2857117f1b4Smrg 2867117f1b4Smrg if (id == 0) { 2877117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)"); 2887117f1b4Smrg return; 2897117f1b4Smrg } 2907117f1b4Smrg 291cdc920a0Smrg q = _mesa_lookup_query_object(ctx, id); 2927117f1b4Smrg if (!q) { 2937117f1b4Smrg /* create new object */ 2947117f1b4Smrg q = ctx->Driver.NewQueryObject(ctx, id); 2957117f1b4Smrg if (!q) { 2967117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB"); 2977117f1b4Smrg return; 2987117f1b4Smrg } 2997117f1b4Smrg _mesa_HashInsert(ctx->Query.QueryObjects, id, q); 3007117f1b4Smrg } 3017117f1b4Smrg else { 3027117f1b4Smrg /* pre-existing object */ 3037117f1b4Smrg if (q->Active) { 3047117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 3057117f1b4Smrg "glBeginQueryARB(query already active)"); 3067117f1b4Smrg return; 3077117f1b4Smrg } 3087117f1b4Smrg } 3097117f1b4Smrg 310c1f859d4Smrg q->Target = target; 3117117f1b4Smrg q->Active = GL_TRUE; 3127117f1b4Smrg q->Result = 0; 3137117f1b4Smrg q->Ready = GL_FALSE; 3147117f1b4Smrg 3153464ebd5Sriastradh /* XXX should probably refcount query objects */ 3163464ebd5Sriastradh *bindpt = q; 3177117f1b4Smrg 318c1f859d4Smrg ctx->Driver.BeginQuery(ctx, q); 3197117f1b4Smrg} 3207117f1b4Smrg 3217117f1b4Smrg 3224a49301eSmrgstatic void GLAPIENTRY 3237117f1b4Smrg_mesa_EndQueryARB(GLenum target) 3247117f1b4Smrg{ 3253464ebd5Sriastradh struct gl_query_object *q, **bindpt; 3267117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 3277117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 3287117f1b4Smrg 3293464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 3303464ebd5Sriastradh _mesa_debug(ctx, "glEndQuery(%s)\n", _mesa_lookup_enum_by_nr(target)); 3313464ebd5Sriastradh 3327117f1b4Smrg FLUSH_VERTICES(ctx, _NEW_DEPTH); 3337117f1b4Smrg 3343464ebd5Sriastradh bindpt = get_query_binding_point(ctx, target); 3353464ebd5Sriastradh if (!bindpt) { 3363464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); 3373464ebd5Sriastradh return; 3387117f1b4Smrg } 3397117f1b4Smrg 3403464ebd5Sriastradh /* XXX should probably refcount query objects */ 3413464ebd5Sriastradh q = *bindpt; 3423464ebd5Sriastradh *bindpt = NULL; 3433464ebd5Sriastradh 3447117f1b4Smrg if (!q || !q->Active) { 3457117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 3467117f1b4Smrg "glEndQueryARB(no matching glBeginQueryARB)"); 3477117f1b4Smrg return; 3487117f1b4Smrg } 3497117f1b4Smrg 3507117f1b4Smrg q->Active = GL_FALSE; 351c1f859d4Smrg ctx->Driver.EndQuery(ctx, q); 3527117f1b4Smrg} 3537117f1b4Smrg 3547117f1b4Smrg 3553464ebd5Sriastradhstatic void GLAPIENTRY 3567117f1b4Smrg_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) 3577117f1b4Smrg{ 3583464ebd5Sriastradh struct gl_query_object *q, **bindpt; 3597117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 3607117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 3617117f1b4Smrg 3623464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 3633464ebd5Sriastradh _mesa_debug(ctx, "glGetQueryiv(%s, %s)\n", 3643464ebd5Sriastradh _mesa_lookup_enum_by_nr(target), 3653464ebd5Sriastradh _mesa_lookup_enum_by_nr(pname)); 3663464ebd5Sriastradh 3673464ebd5Sriastradh bindpt = get_query_binding_point(ctx, target); 3683464ebd5Sriastradh if (!bindpt) { 3693464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)"); 3703464ebd5Sriastradh return; 3717117f1b4Smrg } 3727117f1b4Smrg 3733464ebd5Sriastradh q = *bindpt; 3743464ebd5Sriastradh 3757117f1b4Smrg switch (pname) { 3767117f1b4Smrg case GL_QUERY_COUNTER_BITS_ARB: 3777117f1b4Smrg *params = 8 * sizeof(q->Result); 3787117f1b4Smrg break; 3797117f1b4Smrg case GL_CURRENT_QUERY_ARB: 3807117f1b4Smrg *params = q ? q->Id : 0; 3817117f1b4Smrg break; 3827117f1b4Smrg default: 3837117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)"); 3847117f1b4Smrg return; 3857117f1b4Smrg } 3867117f1b4Smrg} 3877117f1b4Smrg 3887117f1b4Smrg 3893464ebd5Sriastradhstatic void GLAPIENTRY 3907117f1b4Smrg_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) 3917117f1b4Smrg{ 3927117f1b4Smrg struct gl_query_object *q = NULL; 3937117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 3947117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 3957117f1b4Smrg 3963464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 3973464ebd5Sriastradh _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id, 3983464ebd5Sriastradh _mesa_lookup_enum_by_nr(pname)); 3993464ebd5Sriastradh 4007117f1b4Smrg if (id) 401cdc920a0Smrg q = _mesa_lookup_query_object(ctx, id); 4027117f1b4Smrg 4037117f1b4Smrg if (!q || q->Active) { 4047117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 4057117f1b4Smrg "glGetQueryObjectivARB(id=%d is invalid or active)", id); 4067117f1b4Smrg return; 4077117f1b4Smrg } 4087117f1b4Smrg 4097117f1b4Smrg switch (pname) { 4107117f1b4Smrg case GL_QUERY_RESULT_ARB: 411c1f859d4Smrg if (!q->Ready) 412c1f859d4Smrg ctx->Driver.WaitQuery(ctx, q); 4137117f1b4Smrg /* if result is too large for returned type, clamp to max value */ 4143464ebd5Sriastradh if (q->Target == GL_ANY_SAMPLES_PASSED) { 4153464ebd5Sriastradh if (q->Result) 4163464ebd5Sriastradh *params = GL_TRUE; 4173464ebd5Sriastradh else 4183464ebd5Sriastradh *params = GL_FALSE; 4193464ebd5Sriastradh } else { 4203464ebd5Sriastradh if (q->Result > 0x7fffffff) { 4213464ebd5Sriastradh *params = 0x7fffffff; 4223464ebd5Sriastradh } 4233464ebd5Sriastradh else { 4243464ebd5Sriastradh *params = (GLint)q->Result; 4253464ebd5Sriastradh } 4267117f1b4Smrg } 4277117f1b4Smrg break; 4287117f1b4Smrg case GL_QUERY_RESULT_AVAILABLE_ARB: 429c1f859d4Smrg if (!q->Ready) 430c1f859d4Smrg ctx->Driver.CheckQuery( ctx, q ); 4317117f1b4Smrg *params = q->Ready; 4327117f1b4Smrg break; 4337117f1b4Smrg default: 4347117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)"); 4357117f1b4Smrg return; 4367117f1b4Smrg } 4377117f1b4Smrg} 4387117f1b4Smrg 4397117f1b4Smrg 4403464ebd5Sriastradhstatic void GLAPIENTRY 4417117f1b4Smrg_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) 4427117f1b4Smrg{ 4437117f1b4Smrg struct gl_query_object *q = NULL; 4447117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 4457117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 4467117f1b4Smrg 4473464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 4483464ebd5Sriastradh _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id, 4493464ebd5Sriastradh _mesa_lookup_enum_by_nr(pname)); 4503464ebd5Sriastradh 4517117f1b4Smrg if (id) 452cdc920a0Smrg q = _mesa_lookup_query_object(ctx, id); 4537117f1b4Smrg 4547117f1b4Smrg if (!q || q->Active) { 4557117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 4567117f1b4Smrg "glGetQueryObjectuivARB(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 /* if result is too large for returned type, clamp to max value */ 4653464ebd5Sriastradh if (q->Target == GL_ANY_SAMPLES_PASSED) { 4663464ebd5Sriastradh if (q->Result) 4673464ebd5Sriastradh *params = GL_TRUE; 4683464ebd5Sriastradh else 4693464ebd5Sriastradh *params = GL_FALSE; 4703464ebd5Sriastradh } else { 4713464ebd5Sriastradh if (q->Result > 0xffffffff) { 4723464ebd5Sriastradh *params = 0xffffffff; 4733464ebd5Sriastradh } 4743464ebd5Sriastradh else { 4753464ebd5Sriastradh *params = (GLuint)q->Result; 4763464ebd5Sriastradh } 4777117f1b4Smrg } 4787117f1b4Smrg break; 4797117f1b4Smrg case GL_QUERY_RESULT_AVAILABLE_ARB: 480c1f859d4Smrg if (!q->Ready) 481c1f859d4Smrg ctx->Driver.CheckQuery( ctx, q ); 4827117f1b4Smrg *params = q->Ready; 4837117f1b4Smrg break; 4847117f1b4Smrg default: 4857117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); 4867117f1b4Smrg return; 4877117f1b4Smrg } 4887117f1b4Smrg} 4897117f1b4Smrg 4907117f1b4Smrg 4917117f1b4Smrg/** 4927117f1b4Smrg * New with GL_EXT_timer_query 4937117f1b4Smrg */ 4944a49301eSmrgstatic void GLAPIENTRY 4957117f1b4Smrg_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) 4967117f1b4Smrg{ 4977117f1b4Smrg struct gl_query_object *q = NULL; 4987117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 4997117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 5007117f1b4Smrg 5013464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 5023464ebd5Sriastradh _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id, 5033464ebd5Sriastradh _mesa_lookup_enum_by_nr(pname)); 5043464ebd5Sriastradh 5057117f1b4Smrg if (id) 506cdc920a0Smrg q = _mesa_lookup_query_object(ctx, id); 5077117f1b4Smrg 5087117f1b4Smrg if (!q || q->Active) { 5097117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 5107117f1b4Smrg "glGetQueryObjectui64vARB(id=%d is invalid or active)", id); 5117117f1b4Smrg return; 5127117f1b4Smrg } 5137117f1b4Smrg 5147117f1b4Smrg switch (pname) { 5157117f1b4Smrg case GL_QUERY_RESULT_ARB: 516c1f859d4Smrg if (!q->Ready) 517c1f859d4Smrg ctx->Driver.WaitQuery(ctx, q); 5187117f1b4Smrg *params = q->Result; 5197117f1b4Smrg break; 5207117f1b4Smrg case GL_QUERY_RESULT_AVAILABLE_ARB: 521c1f859d4Smrg if (!q->Ready) 522c1f859d4Smrg ctx->Driver.CheckQuery( ctx, q ); 5237117f1b4Smrg *params = q->Ready; 5247117f1b4Smrg break; 5257117f1b4Smrg default: 5267117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)"); 5277117f1b4Smrg return; 5287117f1b4Smrg } 5297117f1b4Smrg} 5307117f1b4Smrg 5317117f1b4Smrg 5327117f1b4Smrg/** 5337117f1b4Smrg * New with GL_EXT_timer_query 5347117f1b4Smrg */ 5354a49301eSmrgstatic void GLAPIENTRY 5367117f1b4Smrg_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) 5377117f1b4Smrg{ 5387117f1b4Smrg struct gl_query_object *q = NULL; 5397117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 5407117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 5417117f1b4Smrg 5423464ebd5Sriastradh if (MESA_VERBOSE & VERBOSE_API) 5433464ebd5Sriastradh _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id, 5443464ebd5Sriastradh _mesa_lookup_enum_by_nr(pname)); 5453464ebd5Sriastradh 5467117f1b4Smrg if (id) 547cdc920a0Smrg q = _mesa_lookup_query_object(ctx, id); 5487117f1b4Smrg 5497117f1b4Smrg if (!q || q->Active) { 5507117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 5517117f1b4Smrg "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id); 5527117f1b4Smrg return; 5537117f1b4Smrg } 5547117f1b4Smrg 5557117f1b4Smrg switch (pname) { 5567117f1b4Smrg case GL_QUERY_RESULT_ARB: 557c1f859d4Smrg if (!q->Ready) 558c1f859d4Smrg ctx->Driver.WaitQuery(ctx, q); 5597117f1b4Smrg *params = q->Result; 5607117f1b4Smrg break; 5617117f1b4Smrg case GL_QUERY_RESULT_AVAILABLE_ARB: 562c1f859d4Smrg if (!q->Ready) 563c1f859d4Smrg ctx->Driver.CheckQuery( ctx, q ); 5647117f1b4Smrg *params = q->Ready; 5657117f1b4Smrg break; 5667117f1b4Smrg default: 5677117f1b4Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)"); 5687117f1b4Smrg return; 5697117f1b4Smrg } 5707117f1b4Smrg} 5717117f1b4Smrg 5724a49301eSmrg 5734a49301eSmrgvoid 5744a49301eSmrg_mesa_init_queryobj_dispatch(struct _glapi_table *disp) 5754a49301eSmrg{ 5764a49301eSmrg SET_GenQueriesARB(disp, _mesa_GenQueriesARB); 5774a49301eSmrg SET_DeleteQueriesARB(disp, _mesa_DeleteQueriesARB); 5784a49301eSmrg SET_IsQueryARB(disp, _mesa_IsQueryARB); 5794a49301eSmrg SET_BeginQueryARB(disp, _mesa_BeginQueryARB); 5804a49301eSmrg SET_EndQueryARB(disp, _mesa_EndQueryARB); 5814a49301eSmrg SET_GetQueryivARB(disp, _mesa_GetQueryivARB); 5824a49301eSmrg SET_GetQueryObjectivARB(disp, _mesa_GetQueryObjectivARB); 5834a49301eSmrg SET_GetQueryObjectuivARB(disp, _mesa_GetQueryObjectuivARB); 5844a49301eSmrg 5854a49301eSmrg SET_GetQueryObjecti64vEXT(disp, _mesa_GetQueryObjecti64vEXT); 5864a49301eSmrg SET_GetQueryObjectui64vEXT(disp, _mesa_GetQueryObjectui64vEXT); 5874a49301eSmrg} 5884a49301eSmrg 5894a49301eSmrg 5904a49301eSmrg#endif /* FEATURE_queryobj */ 5917117f1b4Smrg 5927117f1b4Smrg 5937117f1b4Smrg/** 5947117f1b4Smrg * Allocate/init the context state related to query objects. 5957117f1b4Smrg */ 5967117f1b4Smrgvoid 5973464ebd5Sriastradh_mesa_init_queryobj(struct gl_context *ctx) 5987117f1b4Smrg{ 5997117f1b4Smrg ctx->Query.QueryObjects = _mesa_NewHashTable(); 6007117f1b4Smrg ctx->Query.CurrentOcclusionObject = NULL; 6017117f1b4Smrg} 6027117f1b4Smrg 6037117f1b4Smrg 6047117f1b4Smrg/** 6057117f1b4Smrg * Callback for deleting a query object. Called by _mesa_HashDeleteAll(). 6067117f1b4Smrg */ 6077117f1b4Smrgstatic void 6087117f1b4Smrgdelete_queryobj_cb(GLuint id, void *data, void *userData) 6097117f1b4Smrg{ 6107117f1b4Smrg struct gl_query_object *q= (struct gl_query_object *) data; 6113464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *)userData; 612c1f859d4Smrg ctx->Driver.DeleteQuery(ctx, q); 6137117f1b4Smrg} 6147117f1b4Smrg 6157117f1b4Smrg 6167117f1b4Smrg/** 6177117f1b4Smrg * Free the context state related to query objects. 6187117f1b4Smrg */ 6197117f1b4Smrgvoid 6203464ebd5Sriastradh_mesa_free_queryobj_data(struct gl_context *ctx) 6217117f1b4Smrg{ 622c1f859d4Smrg _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx); 6237117f1b4Smrg _mesa_DeleteHashTable(ctx->Query.QueryObjects); 6247117f1b4Smrg} 625