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.mielnicz...@gmail.com> --- src/mesa/main/queryobj.c | 88 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 17 deletions(-) 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)"); -- 1.9.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev