Module: Mesa
Branch: master
Commit: 63d010115c7972d854e0583f8f74e8d0c3407fcd
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=63d010115c7972d854e0583f8f74e8d0c3407fcd

Author: Dave Airlie <airl...@redhat.com>
Date:   Tue Aug 17 16:07:23 2010 +1000

r600g: add occlusion query support

Signed-off-by: Dave Airlie <airl...@redhat.com>
Signed-off-by: Jerome Glisse <jgli...@redhat.com>

---

 src/gallium/drivers/r600/r600_blit.c      |   34 +++--
 src/gallium/drivers/r600/r600_context.c   |   13 ++-
 src/gallium/drivers/r600/r600_context.h   |   37 +++++-
 src/gallium/drivers/r600/r600_query.c     |  208 ++++++++++++++++++++++++++++-
 src/gallium/drivers/r600/r600_state.c     |    1 -
 src/gallium/drivers/r600/radeon.h         |   30 +++--
 src/gallium/winsys/r600/drm/r600_state.c  |   36 +++++
 src/gallium/winsys/r600/drm/r600_states.h |   25 +++--
 src/gallium/winsys/r600/drm/r600d.h       |    1 +
 src/gallium/winsys/r600/drm/radeon_ctx.c  |   36 +++++-
 10 files changed, 379 insertions(+), 42 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_blit.c 
b/src/gallium/drivers/r600/r600_blit.c
index db7aef7..aef4fbd 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -32,8 +32,10 @@
 #include "r600_screen.h"
 #include "r600_context.h"
 
-static void r600_blitter_save_states(struct r600_context *rctx)
+static void r600_blitter_save_states(struct pipe_context *ctx)
 {
+       struct r600_context *rctx = r600_context(ctx);
+
        util_blitter_save_blend(rctx->blitter, rctx->blend);
        util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa);
        if (rctx->stencil_ref) {
@@ -47,8 +49,9 @@ static void r600_blitter_save_states(struct r600_context 
*rctx)
        if (rctx->viewport) {
                util_blitter_save_viewport(rctx->blitter, 
&rctx->viewport->state.viewport);
        }
-       if (rctx->clip)
-           util_blitter_save_clip(rctx->blitter, &rctx->clip->state.clip);
+       if (rctx->clip) {
+               util_blitter_save_clip(rctx->blitter, &rctx->clip->state.clip);
+       }
        util_blitter_save_vertex_buffers(rctx->blitter, rctx->nvertex_buffer,
                                        rctx->vertex_buffer);
 
@@ -60,37 +63,44 @@ static void r600_blitter_save_states(struct r600_context 
*rctx)
        rctx->rasterizer = NULL;
        rctx->dsa = NULL;
        rctx->vertex_elements = NULL;
+
+       /* suspend queries */
+       r600_queries_suspend(ctx);
 }
 
 static void r600_clear(struct pipe_context *ctx, unsigned buffers,
-                      const float *rgba, double depth, unsigned stencil)
+                       const float *rgba, double depth, unsigned stencil)
 {
        struct r600_context *rctx = r600_context(ctx);
        struct pipe_framebuffer_state *fb = 
&rctx->framebuffer->state.framebuffer;
 
-       r600_blitter_save_states(rctx);
+       r600_blitter_save_states(ctx);
        util_blitter_clear(rctx->blitter, fb->width, fb->height,
                                fb->nr_cbufs, buffers, rgba, depth,
                                stencil);
+       /* resume queries */
+       r600_queries_resume(ctx);
 }
 
-static void r600_clear_render_target(struct pipe_context *pipe,
+static void r600_clear_render_target(struct pipe_context *ctx,
                                     struct pipe_surface *dst,
                                     const float *rgba,
                                     unsigned dstx, unsigned dsty,
                                     unsigned width, unsigned height)
 {
-       struct r600_context *rctx = r600_context(pipe);
+       struct r600_context *rctx = r600_context(ctx);
        struct pipe_framebuffer_state *fb = 
&rctx->framebuffer->state.framebuffer;
 
-       r600_blitter_save_states(rctx);
+       r600_blitter_save_states(ctx);
        util_blitter_save_framebuffer(rctx->blitter, fb);
 
        util_blitter_clear_render_target(rctx->blitter, dst, rgba,
                                         dstx, dsty, width, height);
+       /* resume queries */
+       r600_queries_resume(ctx);
 }
 
-static void r600_clear_depth_stencil(struct pipe_context *pipe,
+static void r600_clear_depth_stencil(struct pipe_context *ctx,
                                     struct pipe_surface *dst,
                                     unsigned clear_flags,
                                     double depth,
@@ -98,14 +108,16 @@ static void r600_clear_depth_stencil(struct pipe_context 
*pipe,
                                     unsigned dstx, unsigned dsty,
                                     unsigned width, unsigned height)
 {
-       struct r600_context *rctx = r600_context(pipe);
+       struct r600_context *rctx = r600_context(ctx);
        struct pipe_framebuffer_state *fb = 
&rctx->framebuffer->state.framebuffer;
 
-       r600_blitter_save_states(rctx);
+       r600_blitter_save_states(ctx);
        util_blitter_save_framebuffer(rctx->blitter, fb);
 
        util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, 
depth, stencil,
                                         dstx, dsty, width, height);
+       /* resume queries */
+       r600_queries_resume(ctx);
 }
 
 static void r600_resource_copy_region(struct pipe_context *pipe,
diff --git a/src/gallium/drivers/r600/r600_context.c 
b/src/gallium/drivers/r600/r600_context.c
index edde80c..2f59a55 100644
--- a/src/gallium/drivers/r600/r600_context.c
+++ b/src/gallium/drivers/r600/r600_context.c
@@ -34,6 +34,7 @@
 #include "r600_resource.h"
 #include "r600d.h"
 
+
 static void r600_destroy_context(struct pipe_context *context)
 {
        struct r600_context *rctx = r600_context(context);
@@ -46,26 +47,34 @@ void r600_flush(struct pipe_context *ctx, unsigned flags,
 {
        struct r600_context *rctx = r600_context(ctx);
        struct r600_screen *rscreen = rctx->screen;
+       struct r600_query *rquery;
        static int dc = 0;
        char dname[256];
 
+       /* suspend queries */
+       r600_queries_suspend(rctx);
        if (radeon_ctx_pm4(rctx->ctx))
-               return;
+               goto out;
        /* FIXME dumping should be removed once shader support instructions
         * without throwing bad code
         */
        if (!rctx->ctx->cpm4)
                goto out;
        sprintf(dname, "gallium-%08d.bof", dc);
-       if (dc < 1)
+       if (dc < 10)
                radeon_ctx_dump_bof(rctx->ctx, dname);
 #if 1
        radeon_ctx_submit(rctx->ctx);
 #endif
+       LIST_FOR_EACH_ENTRY(rquery, &rctx->query_list, list) {
+               rquery->flushed = true;
+       }
        dc++;
 out:
        rctx->ctx = radeon_ctx_decref(rctx->ctx);
        rctx->ctx = radeon_ctx(rscreen->rw);
+       /* resume queries */
+       r600_queries_resume(rctx);
 }
 
 static void r600_init_config(struct r600_context *rctx)
diff --git a/src/gallium/drivers/r600/r600_context.h 
b/src/gallium/drivers/r600/r600_context.h
index 2ce2972..900aa9f 100644
--- a/src/gallium/drivers/r600/r600_context.h
+++ b/src/gallium/drivers/r600/r600_context.h
@@ -30,9 +30,32 @@
 #include <tgsi/tgsi_parse.h>
 #include <tgsi/tgsi_util.h>
 #include <util/u_blitter.h>
+#include <util/u_double_list.h>
 #include "radeon.h"
 #include "r600_shader.h"
 
+#define R600_QUERY_STATE_STARTED       (1 << 0)
+#define R600_QUERY_STATE_ENDED         (1 << 1)
+#define R600_QUERY_STATE_SUSPENDED     (1 << 2)
+
+struct r600_query {
+       u64                                     result;
+       /* The kind of query. Currently only OQ is supported. */
+       unsigned                                type;
+       /* How many results have been written, in dwords. It's incremented
+        * after end_query and flush. */
+       unsigned                                num_results;
+       /* if we've flushed the query */
+       boolean                                 flushed;
+       unsigned                                state;
+       /* The buffer where query results are stored. */
+       struct radeon_bo                        *buffer;
+       unsigned                                buffer_size;
+       /* linked list of queries */
+       struct list_head                        list;
+       struct radeon_state                     *rstate;
+};
+
 /* XXX move this to a more appropriate place */
 union pipe_states {
        struct pipe_rasterizer_state            rasterizer;
@@ -142,7 +165,8 @@ struct r600_context {
        struct r600_vertex_element      *vertex_elements;
        struct pipe_vertex_buffer       vertex_buffer[PIPE_MAX_ATTRIBS];
        struct pipe_index_buffer        index_buffer;
-       struct pipe_blend_color         blend_color;
+       struct pipe_blend_color         blend_color;
+       struct list_head                query_list;
 };
 
 /* Convenience cast wrapper. */
@@ -151,6 +175,11 @@ static INLINE struct r600_context *r600_context(struct 
pipe_context *pipe)
     return (struct r600_context*)pipe;
 }
 
+static INLINE struct r600_query* r600_query(struct pipe_query* q)
+{
+    return (struct r600_query*)q;
+}
+
 struct r600_context_state *r600_context_state(struct r600_context *rctx, 
unsigned type, const void *state);
 struct r600_context_state *r600_context_state_incref(struct r600_context_state 
*rstate);
 struct r600_context_state *r600_context_state_decref(struct r600_context_state 
*rstate);
@@ -179,4 +208,10 @@ extern int r600_pipe_shader_update(struct pipe_context 
*ctx,
 uint32_t r600_translate_texformat(enum pipe_format format,
                                  const unsigned char *swizzle_view, 
                                  uint32_t *word4_p, uint32_t *yuv_format_p);
+
+/* query */
+extern void r600_queries_resume(struct pipe_context *ctx);
+extern void r600_queries_suspend(struct pipe_context *ctx);
+
+
 #endif
diff --git a/src/gallium/drivers/r600/r600_query.c 
b/src/gallium/drivers/r600/r600_query.c
index 9b02ae6..5929606 100644
--- a/src/gallium/drivers/r600/r600_query.c
+++ b/src/gallium/drivers/r600/r600_query.c
@@ -24,39 +24,233 @@
  *      Jerome Glisse
  *      Corbin Simpson
  */
+#include <errno.h>
 #include <util/u_inlines.h>
 #include <util/u_format.h>
 #include <util/u_memory.h>
 #include "r600_screen.h"
 #include "r600_context.h"
 
-static struct pipe_query *r600_create_query(struct pipe_context *pipe, 
unsigned query_type)
+static struct radeon_state *r600_query_begin(struct r600_context *rctx, struct 
r600_query *rquery)
 {
-       return NULL;
+       struct r600_screen *rscreen = rctx->screen;
+       struct radeon_state *rstate;
+
+       rstate = radeon_state(rscreen->rw, R600_QUERY_BEGIN_TYPE, 
R600_QUERY_BEGIN);
+       if (rstate == NULL)
+               return NULL;
+       rstate->states[R600_QUERY__OFFSET] = rquery->num_results;
+       rstate->bo[0] = radeon_bo_incref(rscreen->rw, rquery->buffer);
+       rstate->nbo = 1;
+       rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+       if (radeon_state_pm4(rstate)) {
+               radeon_state_decref(rstate);
+               return NULL;
+       }
+       return rstate;
+}
+
+static struct radeon_state *r600_query_end(struct r600_context *rctx, struct 
r600_query *rquery)
+{
+       struct r600_screen *rscreen = rctx->screen;
+       struct radeon_state *rstate;
+
+       rstate = radeon_state(rscreen->rw, R600_QUERY_END_TYPE, R600_QUERY_END);
+       if (rstate == NULL)
+               return NULL;
+       rstate->states[R600_QUERY__OFFSET] = rquery->num_results + 8;
+       rstate->bo[0] = radeon_bo_incref(rscreen->rw, rquery->buffer);
+       rstate->nbo = 1;
+       rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+       if (radeon_state_pm4(rstate)) {
+               radeon_state_decref(rstate);
+               return NULL;
+       }
+       return rstate;
 }
 
-static void r600_destroy_query(struct pipe_context *pipe, struct pipe_query 
*query)
+static struct pipe_query *r600_create_query(struct pipe_context *ctx, unsigned 
query_type)
 {
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *q;
+
+       if (query_type != PIPE_QUERY_OCCLUSION_COUNTER)
+               return NULL;
+
+       q = CALLOC_STRUCT(r600_query);
+       if (!q)
+               return NULL;
+
+       q->type = query_type;
+       LIST_ADDTAIL(&q->list, &rctx->query_list);
+       q->buffer_size = 4096;
+
+       q->buffer = radeon_bo(rscreen->rw, 0, q->buffer_size, 1, NULL);
+       if (!q->buffer) {
+               FREE(q);
+               return NULL;
+       }
+       return (struct pipe_query *)q;
+}
+
+static void r600_destroy_query(struct pipe_context *ctx,
+                              struct pipe_query *query)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_query *q = r600_query(query);
+
+       radeon_bo_decref(rscreen->rw, q->buffer);
+       LIST_DEL(&q->list);
        FREE(query);
 }
 
-static void r600_begin_query(struct pipe_context *pipe, struct pipe_query 
*query)
+static void r600_query_result(struct pipe_context *ctx, struct r600_query 
*rquery)
 {
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       u64 start, end;
+       u32 *results;
+       int i;
+
+       radeon_bo_wait(rscreen->rw, rquery->buffer);
+       radeon_bo_map(rscreen->rw, rquery->buffer);
+       results = rquery->buffer->data;
+       for (i = 0; i < rquery->num_results; i += 4) {
+               start = (u64)results[i] | (u64)results[i + 1] << 32;
+               end = (u64)results[i + 2] | (u64)results[i + 3] << 32;
+               if ((start & 0x8000000000000000UL) && (end & 
0x8000000000000000UL)) {
+                       rquery->result += end - start;
+               }
+       }
+       radeon_bo_unmap(rscreen->rw, rquery->buffer);
+       rquery->num_results = 0;
 }
 
-static void r600_end_query(struct pipe_context *pipe, struct pipe_query *query)
+static void r600_query_resume(struct pipe_context *ctx, struct r600_query 
*rquery)
 {
+       struct r600_context *rctx = r600_context(ctx);
+
+       if (rquery->num_results >= ((rquery->buffer_size >> 2) - 2)) {
+               /* running out of space */
+               if (!rquery->flushed) {
+                       ctx->flush(ctx, 0, NULL);
+               }
+               r600_query_result(ctx, rquery);
+       }
+       rquery->rstate = radeon_state_decref(rquery->rstate);
+       rquery->rstate = r600_query_begin(rctx, rquery);
+       rquery->flushed = false;
+}
+
+static void r600_query_suspend(struct pipe_context *ctx, struct r600_query 
*rquery)
+{
+       struct r600_context *rctx = r600_context(ctx);
+
+       rquery->rstate = radeon_state_decref(rquery->rstate);
+       rquery->rstate = r600_query_end(rctx, rquery);
+       rquery->num_results += 16;
 }
 
-static boolean r600_get_query_result(struct pipe_context *pipe,
+static void r600_begin_query(struct pipe_context *ctx, struct pipe_query 
*query)
+{
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *rquery = r600_query(query);
+       int r;
+
+       rquery->state = R600_QUERY_STATE_STARTED;
+       rquery->num_results = 0;
+       rquery->flushed = false;
+       r600_query_resume(ctx, rquery);
+       r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate);
+       if (r == -EBUSY) {
+               /* this shouldn't happen */
+               R600_ERR("had to flush while emitting end query\n");
+               ctx->flush(ctx, 0, NULL);
+               r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate);
+       }
+}
+
+static void r600_end_query(struct pipe_context *ctx, struct pipe_query *query)
+{
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *rquery = r600_query(query);
+       int r;
+
+       rquery->state &= ~R600_QUERY_STATE_STARTED;
+       rquery->state |= R600_QUERY_STATE_ENDED;
+       r600_query_suspend(ctx, rquery);
+       r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate);
+       if (r == -EBUSY) {
+               /* this shouldn't happen */
+               R600_ERR("had to flush while emitting end query\n");
+               ctx->flush(ctx, 0, NULL);
+               r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate);
+       }
+}
+
+void r600_queries_suspend(struct pipe_context *ctx)
+{
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *rquery;
+       int r;
+
+       LIST_FOR_EACH_ENTRY(rquery, &rctx->query_list, list) {
+               if (rquery->state & R600_QUERY_STATE_STARTED) {
+                       r600_query_suspend(ctx, rquery);
+                       r = radeon_ctx_set_query_state(rctx->ctx, 
rquery->rstate);
+                       if (r == -EBUSY) {
+                               /* this shouldn't happen */
+                               R600_ERR("had to flush while emitting end 
query\n");
+                               ctx->flush(ctx, 0, NULL);
+                               r = radeon_ctx_set_query_state(rctx->ctx, 
rquery->rstate);
+                       }
+               }
+               rquery->state |= R600_QUERY_STATE_SUSPENDED;
+       }
+}
+
+void r600_queries_resume(struct pipe_context *ctx)
+{
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *rquery;
+       int r;
+
+       LIST_FOR_EACH_ENTRY(rquery, &rctx->query_list, list) {
+               if (rquery->state & R600_QUERY_STATE_STARTED) {
+                       r600_query_resume(ctx, rquery);
+                       r = radeon_ctx_set_query_state(rctx->ctx, 
rquery->rstate);
+                       if (r == -EBUSY) {
+                               /* this shouldn't happen */
+                               R600_ERR("had to flush while emitting end 
query\n");
+                               ctx->flush(ctx, 0, NULL);
+                               r = radeon_ctx_set_query_state(rctx->ctx, 
rquery->rstate);
+                       }
+               }
+               rquery->state &= ~R600_QUERY_STATE_SUSPENDED;
+       }
+}
+
+static boolean r600_get_query_result(struct pipe_context *ctx,
                                        struct pipe_query *query,
-                                       boolean wait, void *result)
+                                       boolean wait, void *vresult)
 {
+       struct r600_query *rquery = r600_query(query);
+       uint64_t *result = (uint64_t*)vresult;
+
+       if (!rquery->flushed) {
+               ctx->flush(ctx, 0, NULL);
+               rquery->flushed = true;
+       }
+       r600_query_result(ctx, rquery);
+       *result = rquery->result;
+       rquery->result = 0;
        return TRUE;
 }
 
 void r600_init_query_functions(struct r600_context* rctx)
 {
+       LIST_INITHEAD(&rctx->query_list);
+
        rctx->context.create_query = r600_create_query;
        rctx->context.destroy_query = r600_destroy_query;
        rctx->context.begin_query = r600_begin_query;
diff --git a/src/gallium/drivers/r600/r600_state.c 
b/src/gallium/drivers/r600/r600_state.c
index 7d2b61f..3943eba 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -268,7 +268,6 @@ static void r600_set_blend_color(struct pipe_context *ctx,
 static void r600_set_clip_state(struct pipe_context *ctx,
                                const struct pipe_clip_state *state)
 {
-       struct r600_screen *rscreen = r600_screen(ctx->screen);
        struct r600_context *rctx = r600_context(ctx);
        struct r600_context_state *rstate;
 
diff --git a/src/gallium/drivers/r600/radeon.h 
b/src/gallium/drivers/r600/radeon.h
index d36c89d..b2cc74f 100644
--- a/src/gallium/drivers/r600/radeon.h
+++ b/src/gallium/drivers/r600/radeon.h
@@ -151,6 +151,7 @@ struct radeon_ctx *radeon_ctx(struct radeon *radeon);
 struct radeon_ctx *radeon_ctx_decref(struct radeon_ctx *ctx);
 struct radeon_ctx *radeon_ctx_incref(struct radeon_ctx *ctx);
 int radeon_ctx_set_draw(struct radeon_ctx *ctx, struct radeon_draw *draw);
+int radeon_ctx_set_query_state(struct radeon_ctx *ctx, struct radeon_state 
*state);
 int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw);
 int radeon_ctx_pm4(struct radeon_ctx *ctx);
 int radeon_ctx_submit(struct radeon_ctx *ctx);
@@ -191,8 +192,8 @@ struct radeon_ctx {
  * R600/R700
  */
 
-#define R600_NSTATE                            1286
-#define R600_NTYPE                             33
+#define R600_NSTATE                            1288
+#define R600_NTYPE                             35
 
 #define R600_CONFIG                            0
 #define R600_CONFIG_TYPE                               0
@@ -252,14 +253,18 @@ struct radeon_ctx {
 #define R600_CB6_TYPE                          27
 #define R600_CB7                               1276
 #define R600_CB7_TYPE                          28
-#define R600_DB                                1277
-#define R600_DB_TYPE                           29
-#define R600_CLIP                              1278
-#define R600_CLIP_TYPE                         30
-#define R600_VGT                               1284
-#define R600_VGT_TYPE                          31
-#define R600_DRAW                              1285
-#define R600_DRAW_TYPE                         32
+#define R600_QUERY_BEGIN                       1277
+#define R600_QUERY_BEGIN_TYPE                  29
+#define R600_QUERY_END                         1278
+#define R600_QUERY_END_TYPE                    30
+#define R600_DB                                        1279
+#define R600_DB_TYPE                           31
+#define R600_CLIP                              1280
+#define R600_CLIP_TYPE                         32
+#define R600_VGT                               1286
+#define R600_VGT_TYPE                          33
+#define R600_DRAW                              1287
+#define R600_DRAW_TYPE                         34
 
 /* R600_CONFIG */
 #define R600_CONFIG__SQ_CONFIG                 0
@@ -653,4 +658,9 @@ struct radeon_ctx {
 #define R600_CLIP__PA_CL_UCP_W_0  3
 #define R600_CLIP_SIZE  4
 #define R600_CLIP_PM4 128
+/* R600 QUERY BEGIN/END */
+#define R600_QUERY__OFFSET                     0
+#define R600_QUERY_SIZE                                1
+#define R600_QUERY_PM4                         128
+
 #endif
diff --git a/src/gallium/winsys/r600/drm/r600_state.c 
b/src/gallium/winsys/r600/drm/r600_state.c
index 2facec7..9b7c11b 100644
--- a/src/gallium/winsys/r600/drm/r600_state.c
+++ b/src/gallium/winsys/r600/drm/r600_state.c
@@ -38,6 +38,8 @@ static int r600_state_pm4_shader(struct radeon_state *state);
 static int r600_state_pm4_draw(struct radeon_state *state);
 static int r600_state_pm4_config(struct radeon_state *state);
 static int r600_state_pm4_generic(struct radeon_state *state);
+static int r600_state_pm4_query_begin(struct radeon_state *state);
+static int r600_state_pm4_query_end(struct radeon_state *state);
 static int r700_state_pm4_config(struct radeon_state *state);
 static int r700_state_pm4_cb0(struct radeon_state *state);
 static int r700_state_pm4_db(struct radeon_state *state);
@@ -240,6 +242,40 @@ static int r600_state_pm4_config(struct radeon_state 
*state)
        return r600_state_pm4_generic(state);
 }
 
+static int r600_state_pm4_query_begin(struct radeon_state *state)
+{
+       int r;
+
+       state->cpm4 = 0;
+       state->pm4[state->cpm4++] = PKT3(PKT3_EVENT_WRITE, 2);
+       state->pm4[state->cpm4++] = EVENT_TYPE_ZPASS_DONE;
+       state->pm4[state->cpm4++] = state->states[0];
+       state->pm4[state->cpm4++] = 0x0;
+       state->pm4[state->cpm4++] = PKT3(PKT3_NOP, 0);
+       r = radeon_state_reloc(state, state->cpm4, 0);
+       if (r)
+               return r;
+       state->pm4[state->cpm4++] = state->bo[0]->handle;
+       return 0;
+}
+
+static int r600_state_pm4_query_end(struct radeon_state *state)
+{
+       int r;
+
+       state->cpm4 = 0;
+       state->pm4[state->cpm4++] = PKT3(PKT3_EVENT_WRITE, 2);
+       state->pm4[state->cpm4++] = EVENT_TYPE_ZPASS_DONE;
+       state->pm4[state->cpm4++] = state->states[0];
+       state->pm4[state->cpm4++] = 0x0;
+       state->pm4[state->cpm4++] = PKT3(PKT3_NOP, 0);
+       r = radeon_state_reloc(state, state->cpm4, 0);
+       if (r)
+               return r;
+       state->pm4[state->cpm4++] = state->bo[0]->handle;
+       return 0;
+}
+
 static int r700_state_pm4_config(struct radeon_state *state)
 {
        state->pm4[state->cpm4++] = PKT3(PKT3_CONTEXT_CONTROL, 1);
diff --git a/src/gallium/winsys/r600/drm/r600_states.h 
b/src/gallium/winsys/r600/drm/r600_states.h
index 2d7a1d3..b5365e4 100644
--- a/src/gallium/winsys/r600/drm/r600_states.h
+++ b/src/gallium/winsys/r600/drm/r600_states.h
@@ -479,6 +479,10 @@ static const struct radeon_register R600_DRAW_names[] = {
        {0x000287F0, 0, 0, "VGT_DRAW_INITIATOR"},
 };
 
+static const struct radeon_register R600_VGT_EVENT_names[] = {
+       {0x00028A90, 1, 0, "VGT_EVENT_INITIATOR"},
+};
+
 static struct radeon_type R600_types[] = {
        { 128,    0, 0x00000000, 0x00000000, 0x0000, 0, "R600_CONFIG", 41, 
r600_state_pm4_config, R600_CONFIG_names},
        { 128,    1, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB_CNTL", 18, 
r600_state_pm4_generic, R600_CB_CNTL_names},
@@ -509,11 +513,12 @@ static struct radeon_type R600_types[] = {
        { 128, 1274, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB5", 7, 
r600_state_pm4_cb0, R600_CB5_names},
        { 128, 1275, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB6", 7, 
r600_state_pm4_cb0, R600_CB6_names},
        { 128, 1276, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB7", 7, 
r600_state_pm4_cb0, R600_CB7_names},
-       { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, 
r600_state_pm4_db, R600_DB_names},
-       { 128, 1278, 0x00028e20, 0x00028e70, 0x0010, 0, "R600_UCP", 4, 
r600_state_pm4_generic, R600_UCP_names},
-       { 128, 1284, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, 
r600_state_pm4_vgt, R600_VGT_names},
-       { 128, 1285, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, 
r600_state_pm4_draw, R600_DRAW_names},
-
+       { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_QUERY_BEGIN", 1, 
r600_state_pm4_query_begin, R600_VGT_EVENT_names},
+       { 128, 1278, 0x00000000, 0x00000000, 0x0000, 0, "R600_QUERY_END", 1, 
r600_state_pm4_query_end, R600_VGT_EVENT_names},
+       { 128, 1279, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, 
r600_state_pm4_db, R600_DB_names},
+       { 128, 1280, 0x00028e20, 0x00028e70, 0x0010, 0, "R600_UCP", 4, 
r600_state_pm4_generic, R600_UCP_names},
+       { 128, 1286, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, 
r600_state_pm4_vgt, R600_VGT_names},
+       { 128, 1287, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, 
r600_state_pm4_draw, R600_DRAW_names},
 };
 
 static struct radeon_type R700_types[] = {
@@ -546,10 +551,12 @@ static struct radeon_type R700_types[] = {
        { 128, 1274, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB5", 7, 
r600_state_pm4_cb0, R600_CB5_names},
        { 128, 1275, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB6", 7, 
r600_state_pm4_cb0, R600_CB6_names},
        { 128, 1276, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB7", 7, 
r600_state_pm4_cb0, R600_CB7_names},
-       { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, 
r700_state_pm4_db, R600_DB_names},
-       { 128, 1278, 0x00028e20, 0x00028e70, 0x0010, 0, "R600_UCP", 4, 
r600_state_pm4_generic, R600_UCP_names},
-       { 128, 1284, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, 
r600_state_pm4_vgt, R600_VGT_names},
-       { 128, 1285, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, 
r600_state_pm4_draw, R600_DRAW_names},
+       { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_QUERY_BEGIN", 1, 
r600_state_pm4_query_begin, R600_VGT_EVENT_names},
+       { 128, 1278, 0x00000000, 0x00000000, 0x0000, 0, "R600_QUERY_END", 1, 
r600_state_pm4_query_end, R600_VGT_EVENT_names},
+       { 128, 1279, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, 
r700_state_pm4_db, R600_DB_names},
+       { 128, 1280, 0x00028e20, 0x00028e70, 0x0010, 0, "R600_UCP", 4, 
r600_state_pm4_generic, R600_UCP_names},
+       { 128, 1286, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, 
r600_state_pm4_vgt, R600_VGT_names},
+       { 128, 1287, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, 
r600_state_pm4_draw, R600_DRAW_names},
 };
 
 #endif
diff --git a/src/gallium/winsys/r600/drm/r600d.h 
b/src/gallium/winsys/r600/drm/r600d.h
index 235b2b3..e8c2dc0 100644
--- a/src/gallium/winsys/r600/drm/r600d.h
+++ b/src/gallium/winsys/r600/drm/r600d.h
@@ -82,6 +82,7 @@
 #define PKT3_SET_CTL_CONST                     0x6F
 #define PKT3_SURFACE_BASE_UPDATE               0x73
 
+#define EVENT_TYPE_ZPASS_DONE                  0x15
 #define EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT   0x16
 
 #define PKT_TYPE_S(x)                   (((x) & 0x3) << 30)
diff --git a/src/gallium/winsys/r600/drm/radeon_ctx.c 
b/src/gallium/winsys/r600/drm/radeon_ctx.c
index 45b706b..bd050c4 100644
--- a/src/gallium/winsys/r600/drm/radeon_ctx.c
+++ b/src/gallium/winsys/r600/drm/radeon_ctx.c
@@ -224,6 +224,41 @@ static int radeon_ctx_state_schedule(struct radeon_ctx 
*ctx, struct radeon_state
        return 0;
 }
 
+int radeon_ctx_set_query_state(struct radeon_ctx *ctx, struct radeon_state 
*state)
+{
+       void *tmp;
+       int r = 0;
+
+       /* !!! ONLY ACCEPT QUERY STATE HERE !!! */
+       if (state->type != R600_QUERY_BEGIN_TYPE && state->type != 
R600_QUERY_END_TYPE) {
+               return -EINVAL;
+       }
+       r = radeon_state_pm4(state);
+       if (r)
+               return r;
+       if ((ctx->draw_cpm4 + state->cpm4) > RADEON_CTX_MAX_PM4) {
+               /* need to flush */
+               return -EBUSY;
+       }
+       if (state->cpm4 >= RADEON_CTX_MAX_PM4) {
+               fprintf(stderr, "%s single state too big %d, max %d\n",
+                       __func__, state->cpm4, RADEON_CTX_MAX_PM4);
+               return -EINVAL;
+       }
+       tmp = realloc(ctx->state, (ctx->nstate + 1) * sizeof(void*));
+       if (tmp == NULL)
+               return -ENOMEM;
+       ctx->state = tmp;
+       ctx->state[ctx->nstate++] = radeon_state_incref(state);
+       /* BEGIN/END query are balanced in the same cs so account for END
+        * END query when scheduling BEGIN query
+        */
+       if (state->type == R600_QUERY_BEGIN_TYPE) {
+               ctx->draw_cpm4 += state->cpm4 * 2;
+       }
+       return 0;
+}
+
 int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw)
 {
        struct radeon_draw *pdraw = NULL;
@@ -366,7 +401,6 @@ printf("%d pm4\n", ctx->cpm4);
                if (bo == NULL)
                        goto out_err;
                size = bof_int32(ctx->bo[i]->size);
-printf("[%d] %d bo\n", i, size);
                if (size == NULL)
                        goto out_err;
                if (bof_object_set(bo, "size", size))

_______________________________________________
mesa-commit mailing list
mesa-commit@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to