📄 queryobj.c
字号:
/* * Mesa 3-D graphics library * Version: 6.5.1 * * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include "glheader.h"#include "context.h"#include "hash.h"#include "imports.h"#include "queryobj.h"#include "mtypes.h"/** * Allocate a new query object. This is a fallback routine called via * ctx->Driver.NewQueryObject(). * \param ctx - rendering context * \param id - the new object's ID * \return pointer to new query_object object or NULL if out of memory. */struct gl_query_object *_mesa_new_query_object(GLcontext *ctx, GLuint id){ struct gl_query_object *q = MALLOC_STRUCT(gl_query_object); (void) ctx; if (q) { q->Id = id; q->Result = 0; q->Active = GL_FALSE; q->Ready = GL_TRUE; /* correct, see spec */ } return q;}/** * Delete an occlusion query object. * Not removed from hash table here. * XXX maybe add Delete() method to gl_query_object class and call that instead */static voiddelete_query_object(struct gl_query_object *q){ FREE(q);}static struct gl_query_object *lookup_query_object(GLcontext *ctx, GLuint id){ return (struct gl_query_object *) _mesa_HashLookup(ctx->Query.QueryObjects, id);}void GLAPIENTRY_mesa_GenQueriesARB(GLsizei n, GLuint *ids){ GLuint first; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); return; } /* No query objects can be active at this time! */ if (ctx->Query.CurrentOcclusionObject || ctx->Query.CurrentTimerObject) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); return; } first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n); if (first) { GLsizei i; for (i = 0; i < n; i++) { struct gl_query_object *q = ctx->Driver.NewQueryObject(ctx, first + i); if (!q) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); return; } ids[i] = first + i; _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q); } }}void GLAPIENTRY_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids){ GLint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); return; } /* No query objects can be active at this time! */ if (ctx->Query.CurrentOcclusionObject || ctx->Query.CurrentTimerObject) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB"); return; } for (i = 0; i < n; i++) { if (ids[i] > 0) { struct gl_query_object *q = lookup_query_object(ctx, ids[i]); if (q) { ASSERT(!q->Active); /* should be caught earlier */ _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]); delete_query_object(q); } } }}GLboolean GLAPIENTRY_mesa_IsQueryARB(GLuint id){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (id && lookup_query_object(ctx, id)) return GL_TRUE; else return GL_FALSE;}void GLAPIENTRY_mesa_BeginQueryARB(GLenum target, GLuint id){ struct gl_query_object *q; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_DEPTH); switch (target) { case GL_SAMPLES_PASSED_ARB: if (!ctx->Extensions.ARB_occlusion_query) { _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); return; } if (ctx->Query.CurrentOcclusionObject) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); return; } break;#if FEATURE_EXT_timer_query case GL_TIME_ELAPSED_EXT: if (!ctx->Extensions.EXT_timer_query) { _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); return; } if (ctx->Query.CurrentTimerObject) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); return; } break;#endif default: _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); return; } if (id == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)"); return; } q = lookup_query_object(ctx, id); if (!q) { /* create new object */ q = ctx->Driver.NewQueryObject(ctx, id); if (!q) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB"); return; } _mesa_HashInsert(ctx->Query.QueryObjects, id, q); } else { /* pre-existing object */ if (q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(query already active)"); return; } } q->Active = GL_TRUE; q->Result = 0; q->Ready = GL_FALSE; if (target == GL_SAMPLES_PASSED_ARB) { ctx->Query.CurrentOcclusionObject = q; }#if FEATURE_EXT_timer_query else if (target == GL_TIME_ELAPSED_EXT) { ctx->Query.CurrentTimerObject = q; }#endif if (ctx->Driver.BeginQuery) { ctx->Driver.BeginQuery(ctx, target, q); }}void GLAPIENTRY_mesa_EndQueryARB(GLenum target){ struct gl_query_object *q; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_DEPTH); switch (target) { case GL_SAMPLES_PASSED_ARB: if (!ctx->Extensions.ARB_occlusion_query) { _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); return; } q = ctx->Query.CurrentOcclusionObject; ctx->Query.CurrentOcclusionObject = NULL; break;#if FEATURE_EXT_timer_query case GL_TIME_ELAPSED_EXT: if (!ctx->Extensions.EXT_timer_query) { _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); return; } q = ctx->Query.CurrentTimerObject; ctx->Query.CurrentTimerObject = NULL; break;#endif default: _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); return; } if (!q || !q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEndQueryARB(no matching glBeginQueryARB)"); return; } q->Active = GL_FALSE; if (ctx->Driver.EndQuery) { ctx->Driver.EndQuery(ctx, target, q); } else { /* if we're using software rendering/querying */ q->Ready = GL_TRUE; }}void GLAPIENTRY_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params){ struct gl_query_object *q; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); switch (target) { case GL_SAMPLES_PASSED_ARB: if (!ctx->Extensions.ARB_occlusion_query) { _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); return; } q = ctx->Query.CurrentOcclusionObject; break;#if FEATURE_EXT_timer_query case GL_TIME_ELAPSED_EXT: if (!ctx->Extensions.EXT_timer_query) { _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); return; } q = ctx->Query.CurrentTimerObject; break;#endif default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)"); return; } switch (pname) { case GL_QUERY_COUNTER_BITS_ARB: *params = 8 * sizeof(q->Result); break; case GL_CURRENT_QUERY_ARB: *params = q ? q->Id : 0; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)"); return; }}void GLAPIENTRY_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params){ struct gl_query_object *q = NULL; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (id) q = lookup_query_object(ctx, id); if (!q || q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryObjectivARB(id=%d is invalid or active)", id); return; } switch (pname) { case GL_QUERY_RESULT_ARB: while (!q->Ready) { /* Wait for the query to finish! */ /* If using software rendering, the result will always be ready * by time we get here. Otherwise, we must be using hardware! */ ASSERT(ctx->Driver.EndQuery); } /* if result is too large for returned type, clamp to max value */ if (q->Result > 0x7fffffff) { *params = 0x7fffffff; } else { *params = q->Result; } break; case GL_QUERY_RESULT_AVAILABLE_ARB: /* XXX revisit when we have a hardware implementation! */ *params = q->Ready; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)"); return; }}void GLAPIENTRY_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params){ struct gl_query_object *q = NULL; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (id) q = lookup_query_object(ctx, id); if (!q || q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryObjectuivARB(id=%d is invalid or active)", id); return; } switch (pname) { case GL_QUERY_RESULT_ARB: while (!q->Ready) { /* Wait for the query to finish! */ /* If using software rendering, the result will always be ready * by time we get here. Otherwise, we must be using hardware! */ ASSERT(ctx->Driver.EndQuery); } /* if result is too large for returned type, clamp to max value */ if (q->Result > 0xffffffff) { *params = 0xffffffff; } else { *params = q->Result; } break; case GL_QUERY_RESULT_AVAILABLE_ARB: /* XXX revisit when we have a hardware implementation! */ *params = q->Ready; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); return; }}#if FEATURE_EXT_timer_query/** * New with GL_EXT_timer_query */void GLAPIENTRY_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params){ struct gl_query_object *q = NULL; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (id) q = lookup_query_object(ctx, id); if (!q || q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryObjectui64vARB(id=%d is invalid or active)", id); return; } switch (pname) { case GL_QUERY_RESULT_ARB: while (!q->Ready) { /* Wait for the query to finish! */ /* If using software rendering, the result will always be ready * by time we get here. Otherwise, we must be using hardware! */ ASSERT(ctx->Driver.EndQuery); } *params = q->Result; break; case GL_QUERY_RESULT_AVAILABLE_ARB: /* XXX revisit when we have a hardware implementation! */ *params = q->Ready; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)"); return; }}/** * New with GL_EXT_timer_query */void GLAPIENTRY_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params){ struct gl_query_object *q = NULL; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (id) q = lookup_query_object(ctx, id); if (!q || q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id); return; } switch (pname) { case GL_QUERY_RESULT_ARB: while (!q->Ready) { /* Wait for the query to finish! */ /* If using software rendering, the result will always be ready * by time we get here. Otherwise, we must be using hardware! */ ASSERT(ctx->Driver.EndQuery); } *params = q->Result; break; case GL_QUERY_RESULT_AVAILABLE_ARB: /* XXX revisit when we have a hardware implementation! */ *params = q->Ready; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)"); return; }}#endif /* FEATURE_EXT_timer_query *//** * Allocate/init the context state related to query objects. */void_mesa_init_query(GLcontext *ctx){#if FEATURE_ARB_occlusion_query ctx->Query.QueryObjects = _mesa_NewHashTable(); ctx->Query.CurrentOcclusionObject = NULL;#endif}/** * Callback for deleting a query object. Called by _mesa_HashDeleteAll(). */static voiddelete_queryobj_cb(GLuint id, void *data, void *userData){ struct gl_query_object *q= (struct gl_query_object *) data; (void) userData; delete_query_object(q);}/** * Free the context state related to query objects. */void_mesa_free_query_data(GLcontext *ctx){ _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, NULL); _mesa_DeleteHashTable(ctx->Query.QueryObjects);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -