[Mesa-dev,5/8] mesa: Store GetQueryObject{ui64}v results in QueryBuffer if bound

Submitted by Rafal Mielniczuk on March 19, 2014, 9:30 p.m.

Details

Message ID 1395264650-13479-6-git-send-email-rafal.mielniczuk2@gmail.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Rafal Mielniczuk March 19, 2014, 9:30 p.m.
If QueryBuffer is bound, store query result in it at given offset,
otherwise store query result in client memory pointer

Signed-off-by: Rafal Mielniczuk <rafal.mielniczuk2@gmail.com>
---
 src/mesa/main/queryobj.c | 88 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 71 insertions(+), 17 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c
index 66250b6..88e80c4 100644
--- a/src/mesa/main/queryobj.c
+++ b/src/mesa/main/queryobj.c
@@ -187,6 +187,44 @@  get_query_binding_point(struct gl_context *ctx, GLenum target)
    }
 }
 
+/**
+ * This function is run by GetQueryObject{ui64}v functions.
+ * It stores the result of the query in QueryBuffer, if it is bound.
+ * Otherwise it just copies the value into params location.
+ */
+static void
+query_store_result(struct gl_context *ctx, void *params,
+                   GLuint size, void *data, const char *caller)
+{
+   /* Page 44 of the OpenGL 4.4 spec says:
+    *
+    *     "Initially, zero is bound to the QUERY_BUFFER binding point,
+    *     indicating that params is a pointer into client memory.
+    *     However, if a non-zero buffer object is bound as the current query
+    *     result buffer (see section 6.1), then params is treated as an offset
+    *     into the designated buffer object."
+    */
+   if (ctx->QueryBuffer != ctx->Shared->NullBufferObj) {
+      GLsizeiptr offset = (GLsizeiptr)params;
+
+      /* ARB_query_buffer_object spec says:
+       *
+       *     "An INVALID_OPERATION error is generated if the command would
+       *     cause data to be written beyond the bounds of the buffer currently
+       *     bound to the QUERY_BUFFER target."
+       */
+      if (offset + size > ctx->QueryBuffer->Size) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(buffer bounds exceeded)", caller);
+         return;
+      }
+
+      ctx->Driver.BufferSubData(ctx, offset, size, data,
+                                ctx->QueryBuffer);
+   } else {
+      memcpy(params, data, size);
+   }
+}
 
 void GLAPIENTRY
 _mesa_GenQueries(GLsizei n, GLuint *ids)
@@ -599,28 +637,34 @@  _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params)
             break;
          //else fall through
       case GL_QUERY_RESULT_ARB:
+      {
+         GLint result = 0;
          if (!q->Ready)
             ctx->Driver.WaitQuery(ctx, q);
          /* if result is too large for returned type, clamp to max value */
          if (q->Target == GL_ANY_SAMPLES_PASSED
              || q->Target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) {
             if (q->Result)
-               *params = GL_TRUE;
+               result = GL_TRUE;
             else
-               *params = GL_FALSE;
+               result = GL_FALSE;
          } else {
             if (q->Result > 0x7fffffff) {
-               *params = 0x7fffffff;
+               result = 0x7fffffff;
             }
             else {
-               *params = (GLint)q->Result;
+               result = (GLint)q->Result;
             }
          }
+         query_store_result(ctx, params, sizeof(result), &result,
+                            "glGetQueryObjectivARB");
          break;
+      }
       case GL_QUERY_RESULT_AVAILABLE_ARB:
 	 if (!q->Ready)
 	    ctx->Driver.CheckQuery( ctx, q );
-         *params = q->Ready;
+         query_store_result(ctx, params, sizeof(q->Ready), &q->Ready,
+                            "glGetQueryObjectivARB");
          break;
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)");
@@ -628,7 +672,6 @@  _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params)
    }
 }
 
-
 void GLAPIENTRY
 _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
 {
@@ -654,28 +697,35 @@  _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
             break;
          //else fall through
       case GL_QUERY_RESULT_ARB:
+      {
+         GLuint result = 0;
          if (!q->Ready)
             ctx->Driver.WaitQuery(ctx, q);
          /* if result is too large for returned type, clamp to max value */
          if (q->Target == GL_ANY_SAMPLES_PASSED
              || q->Target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) {
-            if (q->Result)
-               *params = GL_TRUE;
-            else
-               *params = GL_FALSE;
+            if (q->Result) {
+               result = GL_TRUE;
+            } else {
+               result = GL_FALSE;
+            }
          } else {
             if (q->Result > 0xffffffff) {
-               *params = 0xffffffff;
+               result = 0xffffffff;
             }
             else {
-               *params = (GLuint)q->Result;
+               result = (GLuint)q->Result;
             }
          }
+         query_store_result(ctx, params, sizeof(result), &result,
+                            "glGetQueryObjectuivARB");
          break;
+      }
       case GL_QUERY_RESULT_AVAILABLE_ARB:
 	 if (!q->Ready)
 	    ctx->Driver.CheckQuery( ctx, q );
-         *params = q->Ready;
+         query_store_result(ctx, params, sizeof(q->Ready), &q->Ready,
+                            "glGetQueryObjectuivARB");;
          break;
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)");
@@ -714,12 +764,14 @@  _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params)
       case GL_QUERY_RESULT_ARB:
          if (!q->Ready)
             ctx->Driver.WaitQuery(ctx, q);
-         *params = q->Result;
+         query_store_result(ctx, params, sizeof(q->Result), &q->Result,
+                            "glGetQueryObjecti64vARB");
          break;
       case GL_QUERY_RESULT_AVAILABLE_ARB:
 	 if (!q->Ready)
 	    ctx->Driver.CheckQuery( ctx, q );
-         *params = q->Ready;
+         query_store_result(ctx, params, sizeof(q->Ready), &q->Ready,
+                            "glGetQueryObjecti64vARB");
          break;
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)");
@@ -758,12 +810,14 @@  _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params)
       case GL_QUERY_RESULT_ARB:
          if (!q->Ready)
             ctx->Driver.WaitQuery(ctx, q);
-         *params = q->Result;
+         query_store_result(ctx, params, sizeof(q->Result), &q->Result,
+                            "glGetQueryObjectui64vARB");
          break;
       case GL_QUERY_RESULT_AVAILABLE_ARB:
 	 if (!q->Ready)
 	    ctx->Driver.CheckQuery( ctx, q );
-         *params = q->Ready;
+         query_store_result(ctx, params, sizeof(q->Ready), &q->Ready,
+                            "glGetQueryObjectui64vARB");
          break;
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)");