⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 queryobj.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 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 + -