X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fqueryobj.c;h=b482b1518de8fcc58d60125cfa7b108eae098ef7;hb=c7df9c0e12e000f3d2fd57ebb3072f4afbda8579;hp=8874397720633fe65e36118388fd84b878ff07f8;hpb=4926c5748028d33da4808f8a5473aa7b2f2bdc62;p=mesa.git diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c index 88743977206..b482b1518de 100644 --- a/src/mesa/main/queryobj.c +++ b/src/mesa/main/queryobj.c @@ -25,16 +25,15 @@ #include "glheader.h" #include "context.h" +#include "enums.h" #include "hash.h" #include "imports.h" #include "queryobj.h" +#include "mfeatures.h" #include "mtypes.h" #include "main/dispatch.h" -#if FEATURE_queryobj - - /** * Allocate a new query object. This is a fallback routine called via * ctx->Driver.NewQueryObject(). @@ -51,7 +50,12 @@ _mesa_new_query_object(struct gl_context *ctx, GLuint id) q->Id = id; q->Result = 0; q->Active = GL_FALSE; - q->Ready = GL_TRUE; /* correct, see spec */ + + /* This is to satisfy the language of the specification: "In the initial + * state of a query object, the result is available" (OpenGL 3.1 § + * 2.13). + */ + q->Ready = GL_TRUE; } return q; } @@ -143,12 +147,22 @@ get_query_binding_point(struct gl_context *ctx, GLenum target) return &ctx->Query.CurrentOcclusionObject; else return NULL; + case GL_ANY_SAMPLES_PASSED: + if (ctx->Extensions.ARB_occlusion_query2) + return &ctx->Query.CurrentOcclusionObject; + else + return NULL; + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + if (ctx->Extensions.ARB_ES3_compatibility + || (ctx->API == API_OPENGLES2 && ctx->Version >= 30)) + return &ctx->Query.CurrentOcclusionObject; + else + return NULL; case GL_TIME_ELAPSED_EXT: if (ctx->Extensions.EXT_timer_query) return &ctx->Query.CurrentTimerObject; else return NULL; -#if FEATURE_EXT_transform_feedback case GL_PRIMITIVES_GENERATED: if (ctx->Extensions.EXT_transform_feedback) return &ctx->Query.PrimitivesGenerated; @@ -159,7 +173,6 @@ get_query_binding_point(struct gl_context *ctx, GLenum target) return &ctx->Query.PrimitivesWritten; else return NULL; -#endif default: return NULL; } @@ -167,12 +180,15 @@ get_query_binding_point(struct gl_context *ctx, GLenum target) void GLAPIENTRY -_mesa_GenQueriesARB(GLsizei n, GLuint *ids) +_mesa_GenQueries(GLsizei n, GLuint *ids) { GLuint first; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGenQueries(%d)\n", n); + if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); return; @@ -203,11 +219,15 @@ _mesa_GenQueriesARB(GLsizei n, GLuint *ids) void GLAPIENTRY -_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) +_mesa_DeleteQueries(GLsizei n, const GLuint *ids) { GLint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, 0); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDeleteQueries(%d)\n", n); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); @@ -235,53 +255,102 @@ _mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) GLboolean GLAPIENTRY -_mesa_IsQueryARB(GLuint id) +_mesa_IsQuery(GLuint id) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glIsQuery(%u)\n", id); + if (id && _mesa_lookup_query_object(ctx, id)) return GL_TRUE; else return GL_FALSE; } +static GLboolean +query_error_check_index(struct gl_context *ctx, GLenum target, GLuint index) +{ + switch (target) { + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + case GL_PRIMITIVES_GENERATED: + if (index >= ctx->Const.MaxVertexStreams) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBeginQueryIndexed(index>=MaxVertexStreams)"); + return GL_FALSE; + } + break; + default: + if (index > 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBeginQueryIndexed(index>0)"); + return GL_FALSE; + } + } + return GL_TRUE; +} -static void GLAPIENTRY -_mesa_BeginQueryARB(GLenum target, GLuint id) +void GLAPIENTRY +_mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id) { struct gl_query_object *q, **bindpt; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBeginQueryIndexed(%s, %u, %u)\n", + _mesa_lookup_enum_by_nr(target), index, id); + + if (!query_error_check_index(ctx, target, index)) + return; + FLUSH_VERTICES(ctx, _NEW_DEPTH); bindpt = get_query_binding_point(ctx, target); if (!bindpt) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQuery{Indexed}(target)"); + return; + } + + /* From the GL_ARB_occlusion_query spec: + * + * "If BeginQueryARB is called while another query is already in + * progress with the same target, an INVALID_OPERATION error is + * generated." + */ + if (*bindpt) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginQuery{Indexed}(target=%s is active)", + _mesa_lookup_enum_by_nr(target)); return; } if (id == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQuery{Indexed}(id==0)"); return; } q = _mesa_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"); + if (ctx->API != API_OPENGL_COMPAT) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginQuery{Indexed}(non-gen name)"); return; + } else { + /* create new object */ + q = ctx->Driver.NewQueryObject(ctx, id); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQuery{Indexed}"); + return; + } + _mesa_HashInsert(ctx->Query.QueryObjects, id, q); } - _mesa_HashInsert(ctx->Query.QueryObjects, id, q); } else { /* pre-existing object */ if (q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glBeginQueryARB(query already active)"); + "glBeginQuery{Indexed}(query already active)"); return; } } @@ -298,28 +367,45 @@ _mesa_BeginQueryARB(GLenum target, GLuint id) } -static void GLAPIENTRY -_mesa_EndQueryARB(GLenum target) +void GLAPIENTRY +_mesa_EndQueryIndexed(GLenum target, GLuint index) { struct gl_query_object *q, **bindpt; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glEndQueryIndexed(%s, %u)\n", + _mesa_lookup_enum_by_nr(target), index); + + if (!query_error_check_index(ctx, target, index)) + return; + FLUSH_VERTICES(ctx, _NEW_DEPTH); bindpt = get_query_binding_point(ctx, target); if (!bindpt) { - _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQuery{Indexed}(target)"); return; } /* XXX should probably refcount query objects */ q = *bindpt; + + /* Check for GL_ANY_SAMPLES_PASSED vs GL_SAMPLES_PASSED. */ + if (q && q->Target != target) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEndQuery(target=%s with active query of target %s)", + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(q->Target)); + return; + } + *bindpt = NULL; if (!q || !q->Active) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glEndQueryARB(no matching glBeginQueryARB)"); + "glEndQuery{Indexed}(no matching glBeginQuery{Indexed})"); return; } @@ -327,43 +413,167 @@ _mesa_EndQueryARB(GLenum target) ctx->Driver.EndQuery(ctx, q); } +void GLAPIENTRY +_mesa_BeginQuery(GLenum target, GLuint id) +{ + _mesa_BeginQueryIndexed(target, 0, id); +} void GLAPIENTRY -_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) +_mesa_EndQuery(GLenum target) { - struct gl_query_object *q, **bindpt; + _mesa_EndQueryIndexed(target, 0); +} + +void GLAPIENTRY +_mesa_QueryCounter(GLuint id, GLenum target) +{ + struct gl_query_object *q; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - bindpt = get_query_binding_point(ctx, target); - if (!bindpt) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)"); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glQueryCounter(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(target)); + + /* error checking */ + if (target != GL_TIMESTAMP) { + _mesa_error(ctx, GL_INVALID_ENUM, "glQueryCounter(target)"); return; } - q = *bindpt; + if (id == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glQueryCounter(id==0)"); + return; + } + + q = _mesa_lookup_query_object(ctx, id); + if (!q) { + /* XXX the Core profile should throw INVALID_OPERATION here */ + + /* create new object */ + q = ctx->Driver.NewQueryObject(ctx, id); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glQueryCounter"); + return; + } + _mesa_HashInsert(ctx->Query.QueryObjects, id, q); + } + else { + if (q->Target && q->Target != GL_TIMESTAMP) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glQueryCounter(id has an invalid target)"); + return; + } + } + + if (q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glQueryCounter(id is active)"); + return; + } + + q->Target = target; + q->Result = 0; + q->Ready = GL_FALSE; + + /* QueryCounter is implemented using EndQuery without BeginQuery + * in drivers. This is actually Direct3D and Gallium convention. */ + ctx->Driver.EndQuery(ctx, q); +} + + +void GLAPIENTRY +_mesa_GetQueryIndexediv(GLenum target, GLuint index, GLenum pname, + GLint *params) +{ + struct gl_query_object *q = NULL, **bindpt = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryIndexediv(%s, %u, %s)\n", + _mesa_lookup_enum_by_nr(target), + index, + _mesa_lookup_enum_by_nr(pname)); + + if (!query_error_check_index(ctx, target, index)) + return; + + if (target == GL_TIMESTAMP) { + if (!ctx->Extensions.ARB_timer_query) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)"); + return; + } + } + else { + bindpt = get_query_binding_point(ctx, target); + if (!bindpt) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQuery{Indexed}iv(target)"); + return; + } + + q = *bindpt; + } switch (pname) { case GL_QUERY_COUNTER_BITS_ARB: - *params = 8 * sizeof(q->Result); + switch (target) { + case GL_SAMPLES_PASSED: + *params = ctx->Const.QueryCounterBits.SamplesPassed; + break; + case GL_ANY_SAMPLES_PASSED: + /* The minimum value of this is 1 if it's nonzero, and the value + * is only ever GL_TRUE or GL_FALSE, so no sense in reporting more + * bits. + */ + *params = 1; + break; + case GL_TIME_ELAPSED: + *params = ctx->Const.QueryCounterBits.TimeElapsed; + break; + case GL_TIMESTAMP: + *params = ctx->Const.QueryCounterBits.Timestamp; + break; + case GL_PRIMITIVES_GENERATED: + *params = ctx->Const.QueryCounterBits.PrimitivesGenerated; + break; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + *params = ctx->Const.QueryCounterBits.PrimitivesWritten; + break; + default: + _mesa_problem(ctx, + "Unknown target in glGetQueryIndexediv(target = %s)", + _mesa_lookup_enum_by_nr(target)); + *params = 0; + break; + } break; case GL_CURRENT_QUERY_ARB: - *params = q ? q->Id : 0; + *params = (q && q->Target == target) ? q->Id : 0; break; default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)"); + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQuery{Indexed}iv(pname)"); return; } } +void GLAPIENTRY +_mesa_GetQueryiv(GLenum target, GLenum pname, GLint *params) +{ + _mesa_GetQueryIndexediv(target, 0, pname, params); +} void GLAPIENTRY -_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) +_mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params) { struct gl_query_object *q = NULL; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -378,11 +588,19 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) if (!q->Ready) ctx->Driver.WaitQuery(ctx, q); /* if result is too large for returned type, clamp to max value */ - if (q->Result > 0x7fffffff) { - *params = 0x7fffffff; - } - else { - *params = (GLint)q->Result; + if (q->Target == GL_ANY_SAMPLES_PASSED + || q->Target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) { + if (q->Result) + *params = GL_TRUE; + else + *params = GL_FALSE; + } else { + if (q->Result > 0x7fffffff) { + *params = 0x7fffffff; + } + else { + *params = (GLint)q->Result; + } } break; case GL_QUERY_RESULT_AVAILABLE_ARB: @@ -398,12 +616,16 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) void GLAPIENTRY -_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) +_mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) { struct gl_query_object *q = NULL; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -418,11 +640,19 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) if (!q->Ready) ctx->Driver.WaitQuery(ctx, q); /* if result is too large for returned type, clamp to max value */ - if (q->Result > 0xffffffff) { - *params = 0xffffffff; - } - else { - *params = (GLuint)q->Result; + if (q->Target == GL_ANY_SAMPLES_PASSED + || q->Target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) { + if (q->Result) + *params = GL_TRUE; + else + *params = GL_FALSE; + } else { + if (q->Result > 0xffffffff) { + *params = 0xffffffff; + } + else { + *params = (GLuint)q->Result; + } } break; case GL_QUERY_RESULT_AVAILABLE_ARB: @@ -440,13 +670,17 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) /** * New with GL_EXT_timer_query */ -static void GLAPIENTRY -_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) +void GLAPIENTRY +_mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params) { struct gl_query_object *q = NULL; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -477,13 +711,17 @@ _mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) /** * New with GL_EXT_timer_query */ -static void GLAPIENTRY -_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) +void GLAPIENTRY +_mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params) { struct gl_query_object *q = NULL; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id, + _mesa_lookup_enum_by_nr(pname)); + if (id) q = _mesa_lookup_query_object(ctx, id); @@ -512,25 +750,31 @@ _mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) void -_mesa_init_queryobj_dispatch(struct _glapi_table *disp) +_mesa_init_queryobj_dispatch(const struct gl_context *ctx, + struct _glapi_table *disp) { - SET_GenQueriesARB(disp, _mesa_GenQueriesARB); - SET_DeleteQueriesARB(disp, _mesa_DeleteQueriesARB); - SET_IsQueryARB(disp, _mesa_IsQueryARB); - SET_BeginQueryARB(disp, _mesa_BeginQueryARB); - SET_EndQueryARB(disp, _mesa_EndQueryARB); - SET_GetQueryivARB(disp, _mesa_GetQueryivARB); - SET_GetQueryObjectivARB(disp, _mesa_GetQueryObjectivARB); - SET_GetQueryObjectuivARB(disp, _mesa_GetQueryObjectuivARB); - - SET_GetQueryObjecti64vEXT(disp, _mesa_GetQueryObjecti64vEXT); - SET_GetQueryObjectui64vEXT(disp, _mesa_GetQueryObjectui64vEXT); + SET_GenQueries(disp, _mesa_GenQueries); + SET_DeleteQueries(disp, _mesa_DeleteQueries); + SET_IsQuery(disp, _mesa_IsQuery); + SET_BeginQuery(disp, _mesa_BeginQuery); + SET_EndQuery(disp, _mesa_EndQuery); + SET_GetQueryiv(disp, _mesa_GetQueryiv); + SET_GetQueryObjectuiv(disp, _mesa_GetQueryObjectuiv); + + if (_mesa_is_desktop_gl(ctx)) { + SET_GetQueryObjectiv(disp, _mesa_GetQueryObjectiv); + SET_QueryCounter(disp, _mesa_QueryCounter); + + SET_GetQueryObjecti64v(disp, _mesa_GetQueryObjecti64v); + SET_GetQueryObjectui64v(disp, _mesa_GetQueryObjectui64v); + + SET_BeginQueryIndexed(disp, _mesa_BeginQueryIndexed); + SET_EndQueryIndexed(disp, _mesa_EndQueryIndexed); + SET_GetQueryIndexediv(disp, _mesa_GetQueryIndexediv); + } } -#endif /* FEATURE_queryobj */ - - /** * Allocate/init the context state related to query objects. */ @@ -539,6 +783,12 @@ _mesa_init_queryobj(struct gl_context *ctx) { ctx->Query.QueryObjects = _mesa_NewHashTable(); ctx->Query.CurrentOcclusionObject = NULL; + + ctx->Const.QueryCounterBits.SamplesPassed = 64; + ctx->Const.QueryCounterBits.TimeElapsed = 64; + ctx->Const.QueryCounterBits.Timestamp = 64; + ctx->Const.QueryCounterBits.PrimitivesGenerated = 64; + ctx->Const.QueryCounterBits.PrimitivesWritten = 64; }