#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 "glapi/dispatch.h"
+#include "main/dispatch.h"
#if FEATURE_queryobj
* \return pointer to new query_object object or NULL if out of memory.
*/
static struct gl_query_object *
-_mesa_new_query_object(GLcontext *ctx, GLuint id)
+_mesa_new_query_object(struct gl_context *ctx, GLuint id)
{
struct gl_query_object *q = MALLOC_STRUCT(gl_query_object);
(void) ctx;
* Called via ctx->Driver.BeginQuery().
*/
static void
-_mesa_begin_query(GLcontext *ctx, struct gl_query_object *q)
+_mesa_begin_query(struct gl_context *ctx, struct gl_query_object *q)
{
/* no-op */
}
* Called via ctx->Driver.EndQuery().
*/
static void
-_mesa_end_query(GLcontext *ctx, struct gl_query_object *q)
+_mesa_end_query(struct gl_context *ctx, struct gl_query_object *q)
{
q->Ready = GL_TRUE;
}
* Called via ctx->Driver.WaitQuery().
*/
static void
-_mesa_wait_query(GLcontext *ctx, struct gl_query_object *q)
+_mesa_wait_query(struct gl_context *ctx, struct gl_query_object *q)
{
/* For software drivers, _mesa_end_query() should have completed the query.
* For real hardware, implement a proper WaitQuery() driver function,
* Called via ctx->Driver.CheckQuery().
*/
static void
-_mesa_check_query(GLcontext *ctx, struct gl_query_object *q)
+_mesa_check_query(struct gl_context *ctx, struct gl_query_object *q)
{
/* No-op for sw rendering.
* HW drivers may need to flush at this time.
* Not removed from hash table here.
*/
static void
-_mesa_delete_query(GLcontext *ctx, struct gl_query_object *q)
+_mesa_delete_query(struct gl_context *ctx, struct gl_query_object *q)
{
- _mesa_free(q);
+ free(q);
}
}
+/**
+ * Return pointer to the query object binding point for the given target.
+ * \return NULL if invalid target, else the address of binding point
+ */
+static struct gl_query_object **
+get_query_binding_point(struct gl_context *ctx, GLenum target)
+{
+ switch (target) {
+ case GL_SAMPLES_PASSED_ARB:
+ if (ctx->Extensions.ARB_occlusion_query)
+ 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_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;
+ else
+ return NULL;
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ if (ctx->Extensions.EXT_transform_feedback)
+ return &ctx->Query.PrimitivesWritten;
+ else
+ return NULL;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+
void GLAPIENTRY
_mesa_GenQueriesARB(GLsizei n, GLuint *ids)
{
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;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glDeleeteQueries(%d)\n", n);
+
if (n < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)");
return;
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
static void GLAPIENTRY
_mesa_BeginQueryARB(GLenum target, GLuint id)
{
- struct gl_query_object *q;
+ struct gl_query_object *q, **bindpt;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glBeginQuery(%s, %u)\n",
+ _mesa_lookup_enum_by_nr(target), id);
+
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;
- 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;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
- return;
+ bindpt = get_query_binding_point(ctx, target);
+ if (!bindpt) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
+ return;
}
if (id == 0) {
q->Result = 0;
q->Ready = GL_FALSE;
- if (target == GL_SAMPLES_PASSED_ARB) {
- ctx->Query.CurrentOcclusionObject = q;
- }
- else if (target == GL_TIME_ELAPSED_EXT) {
- ctx->Query.CurrentTimerObject = q;
- }
+ /* XXX should probably refcount query objects */
+ *bindpt = q;
ctx->Driver.BeginQuery(ctx, q);
}
static void GLAPIENTRY
_mesa_EndQueryARB(GLenum target)
{
- struct gl_query_object *q;
+ struct gl_query_object *q, **bindpt;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glEndQuery(%s)\n", _mesa_lookup_enum_by_nr(target));
+
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;
- 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;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
- return;
+ bindpt = get_query_binding_point(ctx, target);
+ if (!bindpt) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
+ return;
}
+ /* XXX should probably refcount query objects */
+ q = *bindpt;
+ *bindpt = NULL;
+
if (!q || !q->Active) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glEndQueryARB(no matching glBeginQueryARB)");
void GLAPIENTRY
_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
{
- struct gl_query_object *q;
+ struct gl_query_object *q, **bindpt;
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;
- 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;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)");
- return;
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glGetQueryiv(%s, %s)\n",
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(pname));
+
+ bindpt = get_query_binding_point(ctx, target);
+ if (!bindpt) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)");
+ return;
}
+ q = *bindpt;
+
switch (pname) {
case GL_QUERY_COUNTER_BITS_ARB:
*params = 8 * sizeof(q->Result);
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);
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) {
+ 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:
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);
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) {
+ 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:
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);
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);
* Allocate/init the context state related to query objects.
*/
void
-_mesa_init_queryobj(GLcontext *ctx)
+_mesa_init_queryobj(struct gl_context *ctx)
{
ctx->Query.QueryObjects = _mesa_NewHashTable();
ctx->Query.CurrentOcclusionObject = NULL;
delete_queryobj_cb(GLuint id, void *data, void *userData)
{
struct gl_query_object *q= (struct gl_query_object *) data;
- GLcontext *ctx = (GLcontext *)userData;
+ struct gl_context *ctx = (struct gl_context *)userData;
ctx->Driver.DeleteQuery(ctx, q);
}
* Free the context state related to query objects.
*/
void
-_mesa_free_queryobj_data(GLcontext *ctx)
+_mesa_free_queryobj_data(struct gl_context *ctx)
{
_mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx);
_mesa_DeleteHashTable(ctx->Query.QueryObjects);