diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gallium/drivers/r300/r300_context.c | 24 | ||||
| -rw-r--r-- | src/gallium/drivers/r300/r300_context.h | 32 | ||||
| -rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 79 | ||||
| -rw-r--r-- | src/gallium/drivers/r300/r300_query.c | 57 | ||||
| -rw-r--r-- | src/gallium/drivers/r300/r300_query.h | 7 | ||||
| -rw-r--r-- | src/gallium/drivers/r300/r300_reg.h | 4 | 
6 files changed, 174 insertions, 29 deletions
| diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index c8510bc63e..da67bc29b8 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -88,9 +88,21 @@ static boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode,  static void r300_destroy_context(struct pipe_context* context) {      struct r300_context* r300 = r300_context(context); +    struct r300_query* query, * temp;      draw_destroy(r300->draw); +    /* Free the OQ BO. */ +    context->screen->buffer_destroy(r300->oqbo); + +    /* If there are any queries pending or not destroyed, remove them now. */ +    if (r300->query_list) { +        foreach_s(query, temp, r300->query_list) { +            remove_from_list(query); +            FREE(query); +        } +    } +      FREE(r300->blend_color_state);      FREE(r300->rs_block);      FREE(r300->scissor_state); @@ -145,6 +157,11 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,      r300->context.is_texture_referenced = r300_is_texture_referenced;      r300->context.is_buffer_referenced = r300_is_buffer_referenced; +    r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state); +    r300->rs_block = CALLOC_STRUCT(r300_rs_block); +    r300->scissor_state = CALLOC_STRUCT(r300_scissor_state); +    r300->viewport_state = CALLOC_STRUCT(r300_viewport_state); +      /* Create a Draw. This is used for vert collation and SW TCL. */      r300->draw = draw_create();      /* Enable our renderer. */ @@ -155,10 +172,9 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,       * transform in hardware, always. */      draw_set_viewport_state(r300->draw, &r300_viewport_identity); -    r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state); -    r300->rs_block = CALLOC_STRUCT(r300_rs_block); -    r300->scissor_state = CALLOC_STRUCT(r300_scissor_state); -    r300->viewport_state = CALLOC_STRUCT(r300_viewport_state); +    /* Open up the OQ BO. */ +    r300->oqbo = screen->buffer_create(screen, 4096, +            PIPE_BUFFER_USAGE_VERTEX, 4096);      r300_init_flush_functions(r300); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index fc8a449893..f78492d4aa 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -25,9 +25,13 @@  #include "draw/draw_context.h"  #include "draw/draw_vertex.h" +  #include "pipe/p_context.h" +  #include "tgsi/tgsi_scan.h" +  #include "util/u_memory.h" +#include "util/u_simple_list.h"  #include "r300_clear.h"  #include "r300_query.h" @@ -150,6 +154,29 @@ struct r300_constant_buffer {      unsigned count;  }; +/* Query object. + * + * This is not a subclass of pipe_query because pipe_query is never + * actually fully defined. So, rather than have it as a member, and do + * subclass-style casting, we treat pipe_query as an opaque, and just + * trust that our state tracker does not ever mess up query objects. + */ +struct r300_query { +    /* The kind of query. Currently only OQ is supported. */ +    unsigned type; +    /* Whether this query is currently active. Only active queries will +     * get emitted into the command stream, and only active queries get +     * tallied. */ +    boolean active; +    /* The current count of this query. Required to be at least 32 bits. */ +    unsigned int count; +    /* The offset of this query into the query buffer, in bytes. */ +    unsigned offset; +    /* Linked list members. */ +    struct r300_query* prev; +    struct r300_query* next; +}; +  struct r300_texture {      /* Parent class */      struct pipe_texture tex; @@ -203,6 +230,11 @@ struct r300_context {      /* Offset into the VBO. */      size_t vbo_offset; +    /* Occlusion query buffer. */ +    struct pipe_buffer* oqbo; +    /* Query list. */ +    struct r300_query* query_list; +      /* Various CSO state objects. */      /* Blend state. */      struct r300_blend_state* blend_state; diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 53256fc6dd..bd4d59e6f1 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -319,6 +319,79 @@ void r300_emit_fb_state(struct r300_context* r300,      END_CS;  } +void r300_emit_query_begin(struct r300_context* r300, +                           struct r300_query* query) +{ +    CS_LOCALS(r300); + +    /* XXX This will almost certainly not return good results +     * for overlapping queries. */ +    BEGIN_CS(2); +    OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); +    END_CS; +} + +void r300_emit_query_end(struct r300_context* r300, +                         struct r300_query* query) +{ +    struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; +    CS_LOCALS(r300); + +    if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, +                0, RADEON_GEM_DOMAIN_GTT)) { +        debug_printf("r300: There wasn't room for the OQ buffer!?" +                " Oh noes!\n"); +    } + +    assert(caps->num_frag_pipes); +    BEGIN_CS(6 * caps->num_frag_pipes + 2); +    /* I'm not so sure I like this switch, but it's hard to be elegant +     * when there's so many special cases... +     * +     * So here's the basic idea. For each pipe, enable writes to it only, +     * then put out the relocation for ZPASS_ADDR, taking into account a +     * 4-byte offset for each pipe. RV380 and older are special; they have +     * only two pipes, and the second pipe's enable is on bit 3, not bit 1, +     * so there's a chipset cap for that. */ +    switch (caps->num_frag_pipes) { +        case 4: +            /* pipe 3 only */ +            OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); +            OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); +            OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3), +                    0, RADEON_GEM_DOMAIN_GTT, 0); +        case 3: +            /* pipe 2 only */ +            OUT_CS_REG(R300_SU_REG_DEST, 1 << 2); +            OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); +            OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2), +                    0, RADEON_GEM_DOMAIN_GTT, 0); +        case 2: +            /* pipe 1 only */ +            /* As mentioned above, accomodate RV380 and older. */ +            OUT_CS_REG(R300_SU_REG_DEST, +                    1 << (caps->high_second_pipe ? 3 : 1)); +            OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); +            OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1), +                    0, RADEON_GEM_DOMAIN_GTT, 0); +        case 1: +            /* pipe 0 only */ +            OUT_CS_REG(R300_SU_REG_DEST, 1 << 0); +            OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); +            OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), +                    0, RADEON_GEM_DOMAIN_GTT, 0); +        default: +            debug_printf("r300: Implementation error: Chipset reports %d" +                    " pixel pipes!\n", caps->num_frag_pipes); +            assert(0); +    } + +    /* And, finally, reset it to normal... */ +    OUT_CS_REG(R300_SU_REG_DEST, 0xF); +    END_CS; + +} +  void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs)  {      CS_LOCALS(r300); @@ -615,6 +688,12 @@ validate:              goto validate;          }      } +    /* ...occlusion query buffer... */ +    if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, +                0, RADEON_GEM_DOMAIN_GTT)) { +        r300->context.flush(&r300->context, 0, NULL); +        goto validate; +    }      /* ...and vertex buffer. */      if (r300->vbo) {          if (!r300->winsys->add_buffer(r300->winsys, r300->vbo, diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 8fc61c2dec..b3a8dc12c8 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -25,14 +25,30 @@  static struct pipe_query* r300_create_query(struct pipe_context* pipe,                                              unsigned query_type)  { -    struct r300_query* q = CALLOC_STRUCT(r300_query); +    struct r300_context* r300 = r300_context(pipe); +    struct r300_screen* r300screen = r300_screen(r300->context.screen); +    unsigned query_size = r300screen->caps->num_frag_pipes * 4; +    struct r300_query* q, * qptr; + +    q = CALLOC_STRUCT(r300_query);      q->type = query_type;      assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); -    /* XXX this is to force winsys to give us a GTT buffer */ -    q->buf = pipe->screen->buffer_create(pipe->screen, 64, -            PIPE_BUFFER_USAGE_VERTEX, 64); +    q->active = FALSE; + +    if (!r300->query_list) { +        r300->query_list = q; +    } else if (!is_empty_list(r300->query_list)) { +        qptr = last_elem(r300->query_list); +        q->offset = qptr->offset + query_size; +        insert_at_tail(r300->query_list, q); +    } + +    /* XXX */ +    if (q->offset >= 4096) { +        q->offset = 0; +    }      return (struct pipe_query*)q;  } @@ -40,6 +56,9 @@ static struct pipe_query* r300_create_query(struct pipe_context* pipe,  static void r300_destroy_query(struct pipe_context* pipe,                                 struct pipe_query* query)  { +    struct r300_query* q = (struct r300_query*)query; + +    remove_from_list(q);      FREE(query);  } @@ -49,15 +68,15 @@ static void r300_begin_query(struct pipe_context* pipe,      uint32_t* map;      struct r300_context* r300 = r300_context(pipe);      struct r300_query* q = (struct r300_query*)query; -    CS_LOCALS(r300); -    map = pipe_buffer_map(pipe->screen, q->buf, PIPE_BUFFER_USAGE_CPU_WRITE); +    map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, +            PIPE_BUFFER_USAGE_CPU_WRITE); +    map += q->offset / 4;      *map = ~0; -    pipe_buffer_unmap(pipe->screen, q->buf); +    pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); -    BEGIN_CS(2); -    OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); -    END_CS; +    r300_emit_dirty_state(r300); +    r300_emit_query_begin(r300, q);  }  static void r300_end_query(struct pipe_context* pipe, @@ -65,12 +84,9 @@ static void r300_end_query(struct pipe_context* pipe,  {      struct r300_context* r300 = r300_context(pipe);      struct r300_query* q = (struct r300_query*)query; -    CS_LOCALS(r300); -    BEGIN_CS(4); -    OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); -    OUT_CS_RELOC(q->buf, 0, 0, RADEON_GEM_DOMAIN_GTT, 0); -    END_CS; +    r300_emit_dirty_state(r300); +    r300_emit_query_end(r300, q);  }  static boolean r300_get_query_result(struct pipe_context* pipe, @@ -78,6 +94,7 @@ static boolean r300_get_query_result(struct pipe_context* pipe,                                       boolean wait,                                       uint64_t* result)  { +    struct r300_context* r300 = r300_context(pipe);      struct r300_query* q = (struct r300_query*)query;      uint32_t* map;      uint32_t temp; @@ -89,11 +106,15 @@ static boolean r300_get_query_result(struct pipe_context* pipe,          pipe->flush(pipe, 0, NULL);      } -    map = pipe_buffer_map(pipe->screen, q->buf, PIPE_BUFFER_USAGE_CPU_READ); + +    map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, +            PIPE_BUFFER_USAGE_CPU_WRITE); +    map += q->offset / 4;      temp = *map; -    pipe_buffer_unmap(pipe->screen, q->buf); +    *map = ~0; +    pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); -    if (temp < 0) { +    if (temp == ~0) {          /* Our results haven't been written yet... */          return FALSE;      } diff --git a/src/gallium/drivers/r300/r300_query.h b/src/gallium/drivers/r300/r300_query.h index 6a7646087a..4f50e8f844 100644 --- a/src/gallium/drivers/r300/r300_query.h +++ b/src/gallium/drivers/r300/r300_query.h @@ -29,13 +29,6 @@  struct r300_context; -struct r300_query { -    /* The kind of query. Currently only OQ is supported. */ -    unsigned type; -    /* Buffer object where we want our results to reside. */ -    struct pipe_buffer* buf; -}; -  static INLINE struct r300_query* r300_query(struct pipe_query* q)  {      return (struct r300_query*)q; diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 6825d99870..03cd219cde 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -3312,6 +3312,10 @@ enum {  #define R200_3D_DRAW_IMMD_2      0xC0003500 +/* XXX Oh look, stuff not brought over from docs yet */ + +#define R300_SU_REG_DEST                    0x42C8 +  #endif /* _R300_REG_H */  /* *INDENT-ON* */ | 
