summaryrefslogtreecommitdiffstats
path: root/src/mesa/state_tracker/st_cb_queryobj.c
diff options
context:
space:
mode:
authorJosé Fonseca <jose.r.fonseca@gmail.com>2012-12-09 10:08:13 +0000
committerJosé Fonseca <jfonseca@vmware.com>2012-12-20 16:33:49 +0000
commit3160b0b9fc2b49b0e9fe684b955eebf3691024ff (patch)
tree8125293ed921fa635998dbaefe99d639af7cb609 /src/mesa/state_tracker/st_cb_queryobj.c
parent9976216bf699be092e14b66ba3a3ecfa3859e87f (diff)
downloadexternal_mesa3d-3160b0b9fc2b49b0e9fe684b955eebf3691024ff.zip
external_mesa3d-3160b0b9fc2b49b0e9fe684b955eebf3691024ff.tar.gz
external_mesa3d-3160b0b9fc2b49b0e9fe684b955eebf3691024ff.tar.bz2
mesa/st: Implement GL_TIME_ELAPSED w/ PIPE_QUERY_TIMESTAMP.
ARB/EXT_timer_query's definition of GL_TIME_ELAPSED match precisely the subtraction of two GL_TIMESTAMP queries. And for a lot of drivers, that's precisely how they have to implement internally -- by emitting two hardware timestamp queries. So, to simplify driver implementation, simply allow doing so in the state tracker. Eventually if no driver implements PIPE_QUERY_TIME_ELAPSED then we could retire it. Reviewed-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Marek Olšák <maraeo@gmail.com> Reviewed-by: Brian Paul <brianp@vmware.com>
Diffstat (limited to 'src/mesa/state_tracker/st_cb_queryobj.c')
-rw-r--r--src/mesa/state_tracker/st_cb_queryobj.c85
1 files changed, 67 insertions, 18 deletions
diff --git a/src/mesa/state_tracker/st_cb_queryobj.c b/src/mesa/state_tracker/st_cb_queryobj.c
index b10fd93..98b61f5 100644
--- a/src/mesa/state_tracker/st_cb_queryobj.c
+++ b/src/mesa/state_tracker/st_cb_queryobj.c
@@ -72,6 +72,11 @@ st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
stq->pq = NULL;
}
+ if (stq->pq_begin) {
+ pipe->destroy_query(pipe, stq->pq_begin);
+ stq->pq_begin = NULL;
+ }
+
free(stq);
}
@@ -79,7 +84,8 @@ st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
static void
st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
{
- struct pipe_context *pipe = st_context(ctx)->pipe;
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
struct st_query_object *stq = st_query_object(q);
unsigned type;
@@ -98,29 +104,46 @@ st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
type = PIPE_QUERY_PRIMITIVES_EMITTED;
break;
- case GL_TIME_ELAPSED_EXT:
- type = PIPE_QUERY_TIME_ELAPSED;
+ case GL_TIME_ELAPSED:
+ if (st->has_time_elapsed)
+ type = PIPE_QUERY_TIME_ELAPSED;
+ else
+ type = PIPE_QUERY_TIMESTAMP;
break;
default:
assert(0 && "unexpected query target in st_BeginQuery()");
return;
}
- if (stq->pq && stq->type != type) {
+ if (stq->type != type) {
/* free old query of different type */
- pipe->destroy_query(pipe, stq->pq);
- stq->pq = NULL;
+ if (stq->pq) {
+ pipe->destroy_query(pipe, stq->pq);
+ stq->pq = NULL;
+ }
+ if (stq->pq_begin) {
+ pipe->destroy_query(pipe, stq->pq_begin);
+ stq->pq_begin = NULL;
+ }
stq->type = PIPE_QUERY_TYPES; /* an invalid value */
}
- if (!stq->pq) {
- stq->pq = pipe->create_query(pipe, type);
- stq->type = type;
+ if (q->Target == GL_TIME_ELAPSED &&
+ type == PIPE_QUERY_TIMESTAMP) {
+ /* Determine time elapsed by emitting two timestamp queries. */
+ if (!stq->pq_begin) {
+ stq->pq_begin = pipe->create_query(pipe, type);
+ stq->type = type;
+ }
+ pipe->end_query(pipe, stq->pq_begin);
+ } else {
+ if (!stq->pq) {
+ stq->pq = pipe->create_query(pipe, type);
+ stq->type = type;
+ }
+ pipe->begin_query(pipe, stq->pq);
}
-
assert(stq->type == type);
-
- pipe->begin_query(pipe, stq->pq);
}
@@ -132,7 +155,9 @@ st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
st_flush_bitmap_cache(st_context(ctx));
- if (q->Target == GL_TIMESTAMP && !stq->pq) {
+ if ((q->Target == GL_TIMESTAMP ||
+ q->Target == GL_TIME_ELAPSED) &&
+ !stq->pq) {
stq->pq = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP);
stq->type = PIPE_QUERY_TIMESTAMP;
}
@@ -141,6 +166,33 @@ st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
}
+static boolean
+get_query_result(struct pipe_context *pipe,
+ struct st_query_object *stq,
+ boolean wait)
+{
+ if (!pipe->get_query_result(pipe,
+ stq->pq,
+ wait,
+ (void *)&stq->base.Result)) {
+ return FALSE;
+ }
+
+ if (stq->base.Target == GL_TIME_ELAPSED &&
+ stq->type == PIPE_QUERY_TIMESTAMP) {
+ /* Calculate the elapsed time from the two timestamp queries */
+ GLuint64EXT Result0 = 0;
+ assert(stq->pq_begin);
+ pipe->get_query_result(pipe, stq->pq_begin, TRUE, (void *)&Result0);
+ stq->base.Result -= Result0;
+ } else {
+ assert(!stq->pq_begin);
+ }
+
+ return TRUE;
+}
+
+
static void
st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q)
{
@@ -151,10 +203,7 @@ st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q)
assert(!stq->base.Ready);
while (!stq->base.Ready &&
- !pipe->get_query_result(pipe,
- stq->pq,
- TRUE,
- (void*)&q->Result))
+ !get_query_result(pipe, stq, TRUE))
{
/* nothing */
}
@@ -169,7 +218,7 @@ st_CheckQuery(struct gl_context *ctx, struct gl_query_object *q)
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_query_object *stq = st_query_object(q);
assert(!q->Ready); /* we should not get called if Ready is TRUE */
- q->Ready = pipe->get_query_result(pipe, stq->pq, FALSE, (void*)&q->Result);
+ q->Ready = get_query_result(pipe, stq, FALSE);
}