glsl: add ir_emit_vertex and ir_end_primitive instruction types
[mesa.git] / src / mesa / state_tracker / st_cb_queryobj.c
index aa31b3710b594f9bcc806cc358c1494de5b604d3..24ce6351dce93586557f3599ec7b8baa483c31b7 100644 (file)
 
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
 #include "st_context.h"
 #include "st_cb_queryobj.h"
+#include "st_cb_bitmap.h"
 
 
-#if FEATURE_queryobj
-
 static struct gl_query_object *
 st_NewQueryObject(struct gl_context *ctx, GLuint id)
 {
@@ -71,6 +71,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);
 }
 
@@ -78,12 +83,18 @@ 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;
 
+   st_flush_bitmap_cache(st_context(ctx));
+
    /* convert GL query type to Gallium query type */
    switch (q->Target) {
+   case GL_ANY_SAMPLES_PASSED:
+   case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+      /* fall-through */
    case GL_SAMPLES_PASSED_ARB:
       type = PIPE_QUERY_OCCLUSION_COUNTER;
       break;
@@ -93,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);
 }
 
 
@@ -125,10 +153,46 @@ st_EndQuery(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);
 
+   st_flush_bitmap_cache(st_context(ctx));
+
+   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;
+   }
+
    pipe->end_query(pipe, stq->pq);
 }
 
 
+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)
 {
@@ -139,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,
-                                 &q->Result))
+         !get_query_result(pipe, stq, TRUE))
    {
       /* nothing */
    }
@@ -157,10 +218,17 @@ 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, &q->Result);
+   q->Ready = get_query_result(pipe, stq, FALSE);
 }
 
 
+static uint64_t
+st_GetTimestamp(struct gl_context *ctx)
+{
+   struct pipe_screen *screen = st_context(ctx)->pipe->screen;
+
+   return screen->get_timestamp(screen);
+}
 
 
 void st_init_query_functions(struct dd_function_table *functions)
@@ -171,6 +239,5 @@ void st_init_query_functions(struct dd_function_table *functions)
    functions->EndQuery = st_EndQuery;
    functions->WaitQuery = st_WaitQuery;
    functions->CheckQuery = st_CheckQuery;
+   functions->GetTimestamp = st_GetTimestamp;
 }
-
-#endif /* FEATURE_queryobj */