Commit 3160b0b9 authored by José Fonseca's avatar José Fonseca Committed by Jose Fonseca

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: default avatarDave Airlie <airlied@redhat.com>
Reviewed-by: Marek Olšák's avatarMarek Olšák <maraeo@gmail.com>
Reviewed-by: Brian Paul's avatarBrian Paul <brianp@vmware.com>
parent 9976216b
......@@ -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);
}
......
......@@ -39,6 +39,10 @@ struct st_query_object
{
struct gl_query_object base;
struct pipe_query *pq;
/* Begin TIMESTAMP query for GL_TIME_ELAPSED_EXT queries */
struct pipe_query *pq_begin;
unsigned type; /**< PIPE_QUERY_x */
};
......
......@@ -83,6 +83,7 @@ struct st_context
GLboolean clamp_frag_color_in_shader;
GLboolean clamp_vert_color_in_shader;
boolean has_stencil_export; /**< can do shader stencil export? */
boolean has_time_elapsed;
/* On old libGL's for linux we need to invalidate the drawables
* on glViewpport calls, this is set via a option.
......
......@@ -371,6 +371,7 @@ void st_init_extensions(struct st_context *st)
{ o(ARB_shader_texture_lod), PIPE_CAP_SM3 },
{ o(ARB_shadow), PIPE_CAP_TEXTURE_SHADOW_MAP },
{ o(ARB_texture_non_power_of_two), PIPE_CAP_NPOT_TEXTURES },
{ o(ARB_timer_query), PIPE_CAP_QUERY_TIMESTAMP },
{ o(ARB_transform_feedback2), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME },
{ o(ARB_transform_feedback3), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME },
......@@ -382,7 +383,6 @@ void st_init_extensions(struct st_context *st)
{ o(EXT_texture_filter_anisotropic), PIPE_CAP_ANISOTROPIC_FILTER },
{ o(EXT_texture_mirror_clamp), PIPE_CAP_TEXTURE_MIRROR_CLAMP },
{ o(EXT_texture_swizzle), PIPE_CAP_TEXTURE_SWIZZLE },
{ o(EXT_timer_query), PIPE_CAP_QUERY_TIME_ELAPSED },
{ o(EXT_transform_feedback), PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS },
{ o(AMD_seamless_cubemap_per_texture), PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE },
......@@ -652,9 +652,12 @@ void st_init_extensions(struct st_context *st)
if (ctx->Const.MaxDualSourceDrawBuffers > 0)
ctx->Extensions.ARB_blend_func_extended = GL_TRUE;
if (screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED) &&
screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP)) {
ctx->Extensions.ARB_timer_query = GL_TRUE;
st->has_time_elapsed =
screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED);
if (st->has_time_elapsed ||
ctx->Extensions.ARB_timer_query) {
ctx->Extensions.EXT_timer_query = GL_TRUE;
}
if (ctx->Extensions.ARB_transform_feedback2 &&
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment