Prototype implementation of new GL_EXT_timer_query extension (not finalized yet).
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 2 Sep 2005 13:42:49 +0000 (13:42 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 2 Sep 2005 13:42:49 +0000 (13:42 +0000)
Extends the query mechanism to query elapsed time while rendering.

src/mesa/drivers/common/driverfuncs.c
src/mesa/drivers/x11/glxheader.h
src/mesa/drivers/x11/xm_api.c
src/mesa/drivers/x11/xm_dd.c
src/mesa/drivers/x11/xmesaP.h
src/mesa/main/context.c
src/mesa/main/dd.h
src/mesa/main/extensions.c
src/mesa/main/mtypes.h
src/mesa/main/occlude.c
src/mesa/main/occlude.h

index c027123736f0bf2d464419608b4171825948e0d8..f2e36b78452007af89b4a492843cc0495d5f29bf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5
  *
  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  *
@@ -28,6 +28,7 @@
 #include "buffers.h"
 #include "context.h"
 #include "framebuffer.h"
+#include "occlude.h"
 #include "program.h"
 #include "renderbuffer.h"
 #include "texcompress.h"
@@ -210,6 +211,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
 #endif
 
    /* query objects */
+   driver->NewQueryObject = _mesa_new_query_object;
    driver->BeginQuery = NULL;
    driver->EndQuery = NULL;
 
index 2533d504443eb15645089fd902b4871beec0dfd9..34b613a1bc41288d63a38e73328554dabc8050f8 100644 (file)
@@ -51,6 +51,7 @@
 #  include <X11/extensions/XShm.h>
 # endif
 # include <GL/glx.h>
+# include <sys/time.h>
 
 #endif
 
index 4e71830afe54743ba82ca2f98ca8f4880c08f810..ad9756bb90c89b8c56598c50c31ccb62c6226ca9 100644 (file)
@@ -1689,13 +1689,16 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
    _mesa_enable_1_4_extensions(mesaCtx);
    _mesa_enable_1_5_extensions(mesaCtx);
    _mesa_enable_2_0_extensions(mesaCtx);
-#if SWTC
+#if ENABLE_EXT_texure_compression_s3tc
     if (c->Mesa_DXTn) {
        _mesa_enable_extension(c, "GL_EXT_texture_compression_s3tc");
        _mesa_enable_extension(c, "GL_S3_s3tc");
     }
     _mesa_enable_extension(c, "GL_3DFX_texture_compression_FXT1");
 #endif
+#if ENABLE_EXT_timer_query
+    _mesa_enable_extension(c, "GL_EXT_timer_query");
+#endif
 
    /* finish up xmesa context initializations */
    c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE;
index 7ab09d444d6458fb6fc24bacc6f2eb910dd0ae36..76dec19f53185d388b3ba057101759a3abcacb55 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5
  *
- * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2005  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"),
@@ -1130,6 +1130,78 @@ xmesa_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
 }
 
 
+#if ENABLE_EXT_timer_query
+
+/*
+ * The GL_EXT_timer_query extension is not enabled for the XServer
+ * indirect renderer.  Not sure about how/if wrapping of gettimeofday()
+ * is done, etc.
+ */
+
+struct xmesa_query_object
+{
+   struct gl_query_object Base;
+   struct timeval StartTime;
+};
+
+
+static struct gl_query_object *
+xmesa_new_query_object(GLcontext *ctx, GLuint id)
+{
+   struct xmesa_query_object *q = CALLOC_STRUCT(xmesa_query_object);
+   if (q) {
+      q->Base.Id = id;
+      q->Base.Ready = GL_TRUE;
+   }
+   return &q->Base;
+}
+
+
+static void
+xmesa_begin_query(GLcontext *ctx, GLenum target, struct gl_query_object *q)
+{
+   if (target == GL_TIME_ELAPSED_EXT) {
+      struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
+      (void) gettimeofday(&xq->StartTime, NULL);
+   }
+}
+
+
+/**
+ * Return the difference between the two given times in microseconds.
+ */
+static unsigned int
+time_diff(const struct timeval *t0, const struct timeval *t1)
+{
+   time_t seconds0 = t0->tv_sec & 0xff;  /* 0 .. 255 seconds */
+   time_t seconds1 = t1->tv_sec & 0xff;  /* 0 .. 255 seconds */
+   suseconds_t useconds0 = seconds0 * 1000000 + t0->tv_usec;
+   suseconds_t useconds1 = seconds1 * 1000000 + t1->tv_usec;
+   return useconds1 - useconds0;
+}
+
+
+static void
+xmesa_end_query(GLcontext *ctx, GLenum target, struct gl_query_object *q)
+{
+   if (target == GL_TIME_ELAPSED_EXT) {
+      struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
+      struct timeval endTime;
+      unsigned int dt;
+      (void) gettimeofday(&endTime, NULL);
+      dt = time_diff(&xq->StartTime, &endTime);
+      /* clamp if we'd overflow a 32-bit unsigned int */
+      if (dt >= 0xffffffffU / 1000U)
+         q->Result = 0xffffffffU;
+      else
+         q->Result = dt * 1000; /* result is in nanoseconds! */
+   }
+   q->Ready = GL_TRUE;
+}
+
+#endif /* ENABLE_timer_query */
+
+
 /**
  * Initialize the device driver function table with the functions
  * we implement in this driver.
@@ -1162,11 +1234,17 @@ xmesa_init_driver_functions( XMesaVisual xmvisual,
    }
 #endif
    driver->TestProxyTexImage = test_proxy_teximage;
-#if SWTC
+#if ENABLE_EXT_texure_compression_s3tc
    driver->ChooseTextureFormat = choose_tex_format;
 #else
    (void) choose_tex_format;
 #endif
+
+#if ENABLE_EXT_timer_query
+   driver->NewQueryObject = xmesa_new_query_object;
+   driver->BeginQuery = xmesa_begin_query;
+   driver->EndQuery = xmesa_end_query;
+#endif
 }
 
 
index ee8ea2f574e260da6832d967d70f5fcb0b6b4016..7030afaa119a2887a06d56b2b9b1e62a82c3f2d8 100644 (file)
@@ -539,7 +539,12 @@ extern GLboolean XMesaLoseCurrent(XMesaContext c);
 extern void XMesaReset( void );
 
 
-#define SWTC 0 /* SW texture compression */
+#define ENABLE_EXT_texure_compression_s3tc 0 /* SW texture compression */
 
+#ifdef XFree86Server
+#define ENABLE_EXT_timer_query 0
+#else
+#define ENABLE_EXT_timer_query 1
+#endif
 
 #endif
index 35eeaa6126aaf67323391e72125aae1eedbc7d4c..a09a4dc317768bc6ffdd0f0aefee6a8100f0fc23 100644 (file)
@@ -1047,11 +1047,11 @@ init_attrib_groups( GLcontext *ctx )
    _mesa_init_lighting( ctx );
    _mesa_init_matrix( ctx );
    _mesa_init_multisample( ctx );
-   _mesa_init_occlude( ctx );
    _mesa_init_pixel( ctx );
    _mesa_init_point( ctx );
    _mesa_init_polygon( ctx );
    _mesa_init_program( ctx );
+   _mesa_init_query( ctx );
    _mesa_init_rastpos( ctx );
    _mesa_init_scissor( ctx );
    _mesa_init_shaderobjects (ctx);
@@ -1290,7 +1290,7 @@ _mesa_free_context_data( GLcontext *ctx )
    _mesa_free_viewport_data( ctx );
    _mesa_free_colortables_data( ctx );
    _mesa_free_program_data(ctx);
-   _mesa_free_occlude_data(ctx);
+   _mesa_free_query_data(ctx);
 
 #if FEATURE_ARB_vertex_buffer_object
    _mesa_delete_buffer_object(ctx, ctx->Array.NullBufferObj);
index 311278000f251bb140d0db337f1e9bcc2883107f..0b4903629c25d47de31a2d292349bb97ed66bee8 100644 (file)
@@ -820,8 +820,10 @@ struct dd_function_table {
     * \name Query objects
     */
    /*@{*/
-   void (*BeginQuery)(GLcontext *ctx, struct gl_query_object *q);
-   void (*EndQuery)(GLcontext *ctx, struct gl_query_object *q);
+   struct gl_query_object * (*NewQueryObject)(GLcontext *ctx, GLuint id);
+   void (*BeginQuery)(GLcontext *ctx, GLenum target,
+                      struct gl_query_object *q);
+   void (*EndQuery)(GLcontext *ctx, GLenum target, struct gl_query_object *q);
    /*@}*/
 
 
index 7a2880ac5323040e2ae8b423d9aefcc6cef23e14..d761704e77ae4dc216e636ef36a327c3dbf5d509 100644 (file)
@@ -120,6 +120,7 @@ static const struct {
    { OFF, "GL_EXT_texture_mirror_clamp",       F(EXT_texture_mirror_clamp) },
    { ON,  "GL_EXT_texture_object",             F(EXT_texture_object) },
    { OFF, "GL_EXT_texture_rectangle",          F(NV_texture_rectangle) },
+   { OFF, "GL_EXT_timer_query",                F(EXT_timer_query) },
    { ON,  "GL_EXT_vertex_array",               F(EXT_vertex_array) },
    { OFF, "GL_EXT_vertex_array_set",           F(EXT_vertex_array_set) },
    { OFF, "GL_3DFX_texture_compression_FXT1",  F(TDFX_texture_compression_FXT1) },
index a37ba7ce98ed3572746259c12ca0c4f5f16e5de1..c02b64dd05b24cf9183f51f1cf91f9d864e2d51c 100644 (file)
@@ -1900,7 +1900,6 @@ struct gl_ati_fragment_shader_state
 
 struct gl_query_object
 {
-   GLenum Target;
    GLuint Id;
    GLuint Result;      /* the counter */
    GLboolean Active;   /* inside Begin/EndQuery */
@@ -1912,6 +1911,7 @@ struct gl_query_state
 {
    struct _mesa_HashTable *QueryObjects;
    struct gl_query_object *CurrentOcclusionObject; /* GL_ARB_occlusion_query */
+   struct gl_query_object *CurrentTimerObject;     /* GL_EXT_timer_query */
 };
 
 
@@ -2367,6 +2367,7 @@ struct gl_extensions
    GLboolean EXT_texture_filter_anisotropic;
    GLboolean EXT_texture_lod_bias;
    GLboolean EXT_texture_mirror_clamp;
+   GLboolean EXT_timer_query;
    GLboolean EXT_vertex_array;
    GLboolean EXT_vertex_array_set;
    /* vendor extensions */
index e3c591defdd59ec724c34cfd044ded4e468f0044..e27ba9d42c49234c7a56153adcdfaa09b97b158d 100644 (file)
  */
 
 
-/*
- * Functions to implement the GL_ARB_occlusion_query extension.
- */
-
-
 #include "glheader.h"
 #include "context.h"
 #include "hash.h"
 
 
 /**
- * Allocate a new occlusion query object.
- * \param target - must be GL_SAMPLES_PASSED_ARB at this time
+ * Allocate a new query object.  This is a fallback routine called via
+ * ctx->Driver.NewQueryObject().
+ * \param target - GL_SAMPLES_PASSED_ARB or GL_TIME_ELAPSED_EXT or 0.
+ * \param ctx - rendering context
  * \param id - the object's ID
  * \return pointer to new query_object object or NULL if out of memory.
  */
-static struct gl_query_object *
-new_query_object(GLenum target, GLuint id)
+struct gl_query_object *
+_mesa_new_query_object(GLcontext *ctx, GLuint id)
 {
    struct gl_query_object *q = MALLOC_STRUCT(gl_query_object);
    if (q) {
-      q->Target = target;
       q->Id = id;
       q->Result = 0;
       q->Active = GL_FALSE;
@@ -80,8 +76,8 @@ lookup_query_object(GLcontext *ctx, GLuint id)
 void GLAPIENTRY
 _mesa_GenQueriesARB(GLsizei n, GLuint *ids)
 {
-   GET_CURRENT_CONTEXT(ctx);
    GLuint first;
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (n < 0) {
@@ -90,7 +86,8 @@ _mesa_GenQueriesARB(GLsizei n, GLuint *ids)
    }
 
    /* No query objects can be active at this time! */
-   if (ctx->Query.CurrentOcclusionObject) {
+   if (ctx->Query.CurrentOcclusionObject ||
+       ctx->Query.CurrentTimerObject) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB");
       return;
    }
@@ -99,8 +96,8 @@ _mesa_GenQueriesARB(GLsizei n, GLuint *ids)
    if (first) {
       GLsizei i;
       for (i = 0; i < n; i++) {
-         struct gl_query_object *q = new_query_object(GL_SAMPLES_PASSED_ARB,
-                                                      first + i);
+         struct gl_query_object *q
+            = ctx->Driver.NewQueryObject(ctx, first + i);
          if (!q) {
             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB");
             return;
@@ -115,8 +112,8 @@ _mesa_GenQueriesARB(GLsizei n, GLuint *ids)
 void GLAPIENTRY
 _mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids)
 {
-   GET_CURRENT_CONTEXT(ctx);
    GLint i;
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (n < 0) {
@@ -125,7 +122,8 @@ _mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids)
    }
 
    /* No query objects can be active at this time! */
-   if (ctx->Query.CurrentOcclusionObject) {
+   if (ctx->Query.CurrentOcclusionObject ||
+       ctx->Query.CurrentTimerObject) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB");
       return;
    }
@@ -159,15 +157,36 @@ _mesa_IsQueryARB(GLuint id)
 void GLAPIENTRY
 _mesa_BeginQueryARB(GLenum target, GLuint id)
 {
-   GET_CURRENT_CONTEXT(ctx);
    struct gl_query_object *q;
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    FLUSH_VERTICES(ctx, _NEW_DEPTH);
 
-   if (target != GL_SAMPLES_PASSED_ARB) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
-      return;
+   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;
    }
 
    if (id == 0) {
@@ -175,15 +194,10 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
       return;
    }
 
-   if (ctx->Query.CurrentOcclusionObject) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(target)");
-      return;
-   }
-
    q = lookup_query_object(ctx, id);
    if (!q) {
       /* create new object */
-      q = new_query_object(target, id);
+      q = ctx->Driver.NewQueryObject(ctx, id);
       if (!q) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB");
          return;
@@ -192,11 +206,6 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
    }
    else {
       /* pre-existing object */
-      if (q->Target != target) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glBeginQueryARB(target mismatch)");
-         return;
-      }
       if (q->Active) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glBeginQueryARB(query already active)");
@@ -207,10 +216,16 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
    q->Active = GL_TRUE;
    q->Result = 0;
    q->Ready = GL_FALSE;
-   ctx->Query.CurrentOcclusionObject = q;
+
+   if (target == GL_SAMPLES_PASSED_ARB) {
+      ctx->Query.CurrentOcclusionObject = q;
+   }
+   else if (target == GL_TIME_ELAPSED_EXT) {
+      ctx->Query.CurrentTimerObject = q;
+   }
 
    if (ctx->Driver.BeginQuery) {
-      ctx->Driver.BeginQuery(ctx, q);
+      ctx->Driver.BeginQuery(ctx, target, q);
    }
 }
 
@@ -218,17 +233,29 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
 void GLAPIENTRY
 _mesa_EndQueryARB(GLenum target)
 {
-   GET_CURRENT_CONTEXT(ctx);
    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;
+      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;
@@ -242,9 +269,10 @@ _mesa_EndQueryARB(GLenum target)
 
    q->Active = GL_FALSE;
    if (ctx->Driver.EndQuery) {
-      ctx->Driver.EndQuery(ctx, q);
+      ctx->Driver.EndQuery(ctx, target, q);
    }
    else {
+      /* if we're using software rendering/querying */
       q->Ready = GL_TRUE;
    }
 }
@@ -253,14 +281,25 @@ _mesa_EndQueryARB(GLenum target)
 void GLAPIENTRY
 _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
 {
-   GET_CURRENT_CONTEXT(ctx);
    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;
+      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;
@@ -283,8 +322,8 @@ _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
 void GLAPIENTRY
 _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
 {
-   GET_CURRENT_CONTEXT(ctx);
    struct gl_query_object *q = NULL;
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (id)
@@ -321,8 +360,8 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
 void GLAPIENTRY
 _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
 {
-   GET_CURRENT_CONTEXT(ctx);
    struct gl_query_object *q = NULL;
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (id)
@@ -358,10 +397,10 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
 
 
 /**
- * Allocate/init the context state related to occlusion query objects.
+ * Allocate/init the context state related to query objects.
  */
 void
-_mesa_init_occlude(GLcontext *ctx)
+_mesa_init_query(GLcontext *ctx)
 {
 #if FEATURE_ARB_occlusion_query
    ctx->Query.QueryObjects = _mesa_NewHashTable();
@@ -371,10 +410,10 @@ _mesa_init_occlude(GLcontext *ctx)
 
 
 /**
- * Free the context state related to occlusion query objects.
+ * Free the context state related to query objects.
  */
 void
-_mesa_free_occlude_data(GLcontext *ctx)
+_mesa_free_query_data(GLcontext *ctx)
 {
    while (1) {
       GLuint id = _mesa_HashFirstEntry(ctx->Query.QueryObjects);
index acf19101f1474630cee3fd69b7199c58524a9b0f..cecf7cb2b9ee5a96a0af58a8d4a5142f9f9e7a07 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.0.2
+ * Version:  6.5
  *
- * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2005  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"),
 #define OCCLUDE_H
 
 
+extern struct gl_query_object *
+_mesa_new_query_object(GLcontext *ctx, GLuint id);
+
 extern void
-_mesa_init_occlude(GLcontext *ctx);
+_mesa_init_query(GLcontext *ctx);
 
 extern void
-_mesa_free_occlude_data(GLcontext *ctx);
+_mesa_free_query_data(GLcontext *ctx);
 
 extern void GLAPIENTRY
 _mesa_GenQueriesARB(GLsizei n, GLuint *ids);