Prototype implementation of new GL_EXT_timer_query extension (not finalized yet).
Extends the query mechanism to query elapsed time while rendering.
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 35eeaa6..a09a4dc 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -1047,11 +1047,11 @@
    _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_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);
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 3112780..0b49036 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -820,8 +820,10 @@
     * \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);
    /*@}*/
 
 
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index 7a2880a..d761704 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -120,6 +120,7 @@
    { 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) },
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index a37ba7c..c02b64d 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1900,7 +1900,6 @@
 
 struct gl_query_object
 {
-   GLenum Target;
    GLuint Id;
    GLuint Result;      /* the counter */
    GLboolean Active;   /* inside Begin/EndQuery */
@@ -1912,6 +1911,7 @@
 {
    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 @@
    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 */
diff --git a/src/mesa/main/occlude.c b/src/mesa/main/occlude.c
index e3c591d..e27ba9d 100644
--- a/src/mesa/main/occlude.c
+++ b/src/mesa/main/occlude.c
@@ -23,11 +23,6 @@
  */
 
 
-/*
- * Functions to implement the GL_ARB_occlusion_query extension.
- */
-
-
 #include "glheader.h"
 #include "context.h"
 #include "hash.h"
@@ -37,17 +32,18 @@
 
 
 /**
- * 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 @@
 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 @@
    }
 
    /* 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 @@
    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 @@
 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 @@
    }
 
    /* 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 @@
 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 @@
       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 @@
    }
    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 @@
    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 @@
 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 @@
 
    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 @@
 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 @@
 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 @@
 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 @@
 
 
 /**
- * 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 @@
 
 
 /**
- * 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);
diff --git a/src/mesa/main/occlude.h b/src/mesa/main/occlude.h
index acf1910..cecf7cb 100644
--- a/src/mesa/main/occlude.h
+++ b/src/mesa/main/occlude.h
@@ -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"),
@@ -27,11 +27,14 @@
 #define OCCLUDE_H
 
 
-extern void
-_mesa_init_occlude(GLcontext *ctx);
+extern struct gl_query_object *
+_mesa_new_query_object(GLcontext *ctx, GLuint id);
 
 extern void
-_mesa_free_occlude_data(GLcontext *ctx);
+_mesa_init_query(GLcontext *ctx);
+
+extern void
+_mesa_free_query_data(GLcontext *ctx);
 
 extern void GLAPIENTRY
 _mesa_GenQueriesARB(GLsizei n, GLuint *ids);