diff options
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/i965simple/brw_surface.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_state_validate.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_vbo.c | 190 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_chipset.c | 11 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_chipset.h | 4 | ||||
-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 | 76 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_query.h | 7 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_reg.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_inlines.h | 19 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_winsys.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/trace/tr_dump.c | 2 |
17 files changed, 382 insertions, 80 deletions
diff --git a/src/gallium/drivers/i965simple/brw_surface.c b/src/gallium/drivers/i965simple/brw_surface.c index 511779dbfa..724a69b2ee 100644 --- a/src/gallium/drivers/i965simple/brw_surface.c +++ b/src/gallium/drivers/i965simple/brw_surface.c @@ -60,7 +60,7 @@ brw_surface_copy(struct pipe_context *pipe, src, PIPE_BUFFER_USAGE_CPU_READ ); - pipe_copy_rect(dst_map, + util_copy_rect(dst_map, &dst->block, dst->stride, dstx, dsty, @@ -99,7 +99,7 @@ brw_surface_fill(struct pipe_context *pipe, dst, PIPE_BUFFER_USAGE_CPU_WRITE ); - pipe_fill_rect(dst_map, &dst->block, dst->stride, dstx, dsty, width, height, value); + util_fill_rect(dst_map, &dst->block, dst->stride, dstx, dsty, width, height, value); pipe->screen->surface_unmap(pipe->screen, dst); } diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index 5cbc2c8f82..4de6e8cfa2 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -120,6 +120,7 @@ struct nv50_state { struct nouveau_stateobj *fragprog; struct nouveau_stateobj *vtxfmt; struct nouveau_stateobj *vtxbuf; + struct nouveau_stateobj *vtxattr; }; struct nv50_context { diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index a879df2e6e..99d5b96e45 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -204,6 +204,8 @@ nv50_state_emit(struct nv50_context *nv50) if (nv50->state.dirty & NV50_NEW_ARRAYS) { so_emit(chan, nv50->state.vtxfmt); so_emit(chan, nv50->state.vtxbuf); + if (nv50->state.vtxattr) + so_emit(chan, nv50->state.vtxattr); } nv50->state.dirty = 0; diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 17283f3f41..36f1b24b2f 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -49,55 +49,80 @@ nv50_prim(unsigned mode) return NV50TCL_VERTEX_BEGIN_POINTS; } -static INLINE unsigned -nv50_vtxeltfmt(unsigned pf) +static INLINE uint32_t +nv50_vbo_type_to_hw(unsigned type) { - static const uint8_t vtxelt_32[4] = { 0x90, 0x20, 0x10, 0x08 }; - static const uint8_t vtxelt_16[4] = { 0xd8, 0x78, 0x28, 0x18 }; - static const uint8_t vtxelt_08[4] = { 0xe8, 0xc0, 0x98, 0x50 }; - - unsigned nf, c = 0; - - switch (pf_type(pf)) { + switch (type) { case PIPE_FORMAT_TYPE_FLOAT: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT; case PIPE_FORMAT_TYPE_UNORM: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UNORM; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UNORM; case PIPE_FORMAT_TYPE_SNORM: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SNORM; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SNORM; case PIPE_FORMAT_TYPE_USCALED: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_USCALED; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_USCALED; case PIPE_FORMAT_TYPE_SSCALED: - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SSCALED; break; + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SSCALED; + /* + case PIPE_FORMAT_TYPE_UINT: + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UINT; + case PIPE_FORMAT_TYPE_SINT: + return NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SINT; */ default: - NOUVEAU_ERR("invalid vbo type %d\n",pf_type(pf)); - assert(0); - nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT; - break; + return 0; } +} - if (pf_size_y(pf)) c++; - if (pf_size_z(pf)) c++; - if (pf_size_w(pf)) c++; - - if (pf_exp2(pf) == 3) { - switch (pf_size_x(pf)) { - case 1: return (nf | (vtxelt_08[c] << 16)); - case 2: return (nf | (vtxelt_16[c] << 16)); - case 4: return (nf | (vtxelt_32[c] << 16)); - default: - break; - } - } else - if (pf_exp2(pf) == 6 && pf_size_x(pf) == 1) { - NOUVEAU_ERR("unsupported vbo component size 64\n"); - assert(0); - return (nf | 0x08000000); +static INLINE uint32_t +nv50_vbo_size_to_hw(unsigned size, unsigned nr_c) +{ + static const uint32_t hw_values[] = { + 0, 0, 0, 0, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8_8, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8_8_8, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_8_8_8_8, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16_16, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16_16_16, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_16_16_16_16, + 0, 0, 0, 0, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32_32, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32_32_32, + NV50TCL_VERTEX_ARRAY_ATTRIB_SIZE_32_32_32_32 }; + + /* we'd also have R11G11B10 and R10G10B10A2 */ + + assert(nr_c > 0 && nr_c <= 4); + + if (size > 32) + return 0; + size >>= (3 - 2); + + return hw_values[size + (nr_c - 1)]; +} + +static INLINE uint32_t +nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve) +{ + uint32_t hw_type, hw_size; + enum pipe_format pf = ve->src_format; + unsigned size = pf_size_x(pf) << pf_exp2(pf); + + hw_type = nv50_vbo_type_to_hw(pf_type(pf)); + hw_size = nv50_vbo_size_to_hw(size, ve->nr_components); + + if (!hw_type || !hw_size) { + NOUVEAU_ERR("unsupported vbo format: %s\n", pf_name(pf)); + abort(); + return 0x24e80000; } - NOUVEAU_ERR("invalid vbo format %s\n",pf_name(pf)); - assert(0); - return (nf | 0x08000000); + if (pf_swizzle_x(pf) == 2) /* BGRA */ + hw_size |= (1 << 31); /* no real swizzle bits :-( */ + + return (hw_type | hw_size); } boolean @@ -252,18 +277,78 @@ nv50_draw_elements(struct pipe_context *pipe, return TRUE; } +static INLINE boolean +nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, + struct nouveau_stateobj **pso, + struct pipe_vertex_element *ve, + struct pipe_vertex_buffer *vb) + +{ + struct nouveau_stateobj *so; + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_bo *bo = nouveau_bo(vb->buffer); + float *v; + int ret; + enum pipe_format pf = ve->src_format; + + if ((pf_type(pf) != PIPE_FORMAT_TYPE_FLOAT) || + (pf_size_x(pf) << pf_exp2(pf)) != 32) + return FALSE; + + ret = nouveau_bo_map(bo, NOUVEAU_BO_RD); + if (ret) + return FALSE; + v = (float *)(bo->map + (vb->buffer_offset + ve->src_offset)); + + so = *pso; + if (!so) + *pso = so = so_new(nv50->vtxelt_nr * 5, 0); + + switch (ve->nr_components) { + case 4: + so_method(so, tesla, NV50TCL_VTX_ATTR_4F_X(attrib), 4); + so_data (so, fui(v[0])); + so_data (so, fui(v[1])); + so_data (so, fui(v[2])); + so_data (so, fui(v[3])); + break; + case 3: + so_method(so, tesla, NV50TCL_VTX_ATTR_3F_X(attrib), 4); + so_data (so, fui(v[0])); + so_data (so, fui(v[1])); + so_data (so, fui(v[2])); + break; + case 2: + so_method(so, tesla, NV50TCL_VTX_ATTR_2F_X(attrib), 4); + so_data (so, fui(v[0])); + so_data (so, fui(v[1])); + break; + case 1: + so_method(so, tesla, NV50TCL_VTX_ATTR_1F(attrib), 4); + so_data (so, fui(v[0])); + break; + default: + nouveau_bo_unmap(bo); + return FALSE; + } + + nouveau_bo_unmap(bo); + return TRUE; +} + void nv50_vbo_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_stateobj *vtxbuf, *vtxfmt; - int i; + struct nouveau_stateobj *vtxbuf, *vtxfmt, *vtxattr; + unsigned i; /* don't validate if Gallium took away our buffers */ if (nv50->vtxbuf_nr == 0) return; - vtxbuf = so_new(nv50->vtxelt_nr * 4, nv50->vtxelt_nr * 2); + vtxattr = NULL; + vtxbuf = so_new(nv50->vtxelt_nr * 7, nv50->vtxelt_nr * 4); vtxfmt = so_new(nv50->vtxelt_nr + 1, 0); so_method(vtxfmt, tesla, NV50TCL_VERTEX_ARRAY_ATTRIB(0), nv50->vtxelt_nr); @@ -273,8 +358,18 @@ nv50_vbo_validate(struct nv50_context *nv50) struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index]; struct nouveau_bo *bo = nouveau_bo(vb->buffer); + uint32_t hw = nv50_vbo_vtxelt_to_hw(ve); + + if (!vb->stride && + nv50_vbo_static_attrib(nv50, i, &vtxattr, ve, vb)) { + so_data(vtxfmt, hw | (1 << 4)); - so_data(vtxfmt, nv50_vtxeltfmt(ve->src_format) | i); + so_method(vtxbuf, tesla, + NV50TCL_VERTEX_ARRAY_FORMAT(i), 1); + so_data (vtxbuf, 0); + continue; + } + so_data(vtxfmt, hw | i); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 3); so_data (vtxbuf, 0x20000000 | vb->stride); @@ -284,11 +379,22 @@ nv50_vbo_validate(struct nv50_context *nv50) so_reloc (vtxbuf, bo, vb->buffer_offset + ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + + /* vertex array limits */ + so_method(vtxbuf, tesla, 0x1080 + (i * 8), 2); + so_reloc (vtxbuf, bo, vb->buffer->size - 1, + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | + NOUVEAU_BO_HIGH, 0, 0); + so_reloc (vtxbuf, bo, vb->buffer->size - 1, + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | + NOUVEAU_BO_LOW, 0, 0); } so_ref (vtxfmt, &nv50->state.vtxfmt); so_ref (vtxbuf, &nv50->state.vtxbuf); + so_ref (vtxattr, &nv50->state.vtxattr); so_ref (NULL, &vtxbuf); so_ref (NULL, &vtxfmt); + so_ref (NULL, &vtxattr); } diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 00fae8d26f..d138866d33 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -30,9 +30,11 @@ void r300_parse_chipset(struct r300_capabilities* caps) { /* Reasonable defaults */ + caps->num_vert_fpus = 4; caps->has_tcl = getenv("RADEON_NO_TCL") ? FALSE : TRUE; caps->is_r500 = FALSE; - caps->num_vert_fpus = 4; + caps->high_second_pipe = FALSE; + /* Note: These are not ordered by PCI ID. I leave that task to GCC, * which will perform the ordering while collating jump tables. Instead, @@ -40,6 +42,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) switch (caps->pci_id) { case 0x4144: caps->family = CHIP_FAMILY_R300; + caps->high_second_pipe = TRUE; break; case 0x4145: @@ -50,6 +53,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x4E46: case 0x4E47: caps->family = CHIP_FAMILY_R300; + caps->high_second_pipe = TRUE; break; case 0x4150: @@ -66,6 +70,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x4E54: case 0x4E56: caps->family = CHIP_FAMILY_RV350; + caps->high_second_pipe = TRUE; break; case 0x4148: @@ -76,10 +81,12 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x4E49: case 0x4E4B: caps->family = CHIP_FAMILY_R350; + caps->high_second_pipe = TRUE; break; case 0x4E4A: caps->family = CHIP_FAMILY_R360; + caps->high_second_pipe = TRUE; break; case 0x5460: @@ -91,6 +98,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5B64: case 0x5B65: caps->family = CHIP_FAMILY_RV370; + caps->high_second_pipe = TRUE; break; case 0x3150: @@ -99,6 +107,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x3E50: case 0x3E54: caps->family = CHIP_FAMILY_RV380; + caps->high_second_pipe = TRUE; break; case 0x4A48: diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index 5b2e1f0568..322d4a57e4 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -34,6 +34,8 @@ struct r300_capabilities { int family; /* The number of vertex floating-point units */ int num_vert_fpus; + /* The number of fragment pipes */ + int num_frag_pipes; /* Whether or not TCL is physically present */ boolean has_tcl; /* Whether or not this is an RV515 or newer; R500s have many differences @@ -42,6 +44,8 @@ struct r300_capabilities { * - Blend color is split across two registers * - Universal Shader (US) block used for fragment shaders */ boolean is_r500; + /* Whether or not the second pixel pipe is accessed with the high bit */ + boolean high_second_pipe; }; /* Enumerations for legibility and telling which card we're running on. */ 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..1d5185b417 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,22 +94,38 @@ static boolean r300_get_query_result(struct pipe_context* pipe, boolean wait, uint64_t* result) { + struct r300_context* r300 = r300_context(pipe); + struct r300_screen* r300screen = r300_screen(r300->context.screen); struct r300_query* q = (struct r300_query*)query; + unsigned flags = PIPE_BUFFER_USAGE_CPU_READ; uint32_t* map; uint32_t temp; + unsigned i; if (wait) { - /* Well, we're expected to just sit here and spin, so let's go ahead - * and flush so we can be sure that the card's spinning... */ - /* XXX double-check these params */ pipe->flush(pipe, 0, NULL); + } else { + flags |= PIPE_BUFFER_USAGE_DONTBLOCK; } - map = pipe_buffer_map(pipe->screen, q->buf, PIPE_BUFFER_USAGE_CPU_READ); - temp = *map; - pipe_buffer_unmap(pipe->screen, q->buf); + map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, flags); + map += q->offset / 4; + for (i = 0; i < r300screen->caps->num_frag_pipes; i++) { + if (*map == ~0) { + /* Looks like our results aren't ready yet. */ + if (wait) { + debug_printf("r300: Despite waiting, OQ results haven't" + " come in yet.\n"); + } + temp = ~0; + break; + } + temp += *map; + map++; + } + 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* */ diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 96a7304621..15740f6125 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -392,6 +392,7 @@ struct pipe_screen* r300_create_screen(struct r300_winsys* r300_winsys) return NULL; caps->pci_id = r300_winsys->pci_id; + caps->num_frag_pipes = r300_winsys->gb_pipes; r300_parse_chipset(caps); diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index a02fb34b2a..27680a3863 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -224,7 +224,8 @@ static void* dsa->alpha_reference = CLAMP(state->alpha.ref_value * 1023.0f, 0, 1023); } else { - dsa->z_buffer_top = R300_ZTOP_ENABLE; + /* XXX need to fix this to be dynamically set + dsa->z_buffer_top = R300_ZTOP_ENABLE; */ } return (void*)dsa; diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 22c8e199ae..91b93fc367 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -353,6 +353,25 @@ static INLINE uint32_t r300_translate_out_fmt(enum pipe_format format) /* Non-CSO state. (For now.) */ +static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) +{ + switch (pipe_count) { + case 1: + return R300_GB_TILE_PIPE_COUNT_RV300; + break; + case 2: + return R300_GB_TILE_PIPE_COUNT_R300; + break; + case 3: + return R300_GB_TILE_PIPE_COUNT_R420_3P; + break; + case 4: + return R300_GB_TILE_PIPE_COUNT_R420; + break; + } + return 0; +} + static INLINE uint32_t translate_vertex_data_type(int type) { switch (type) { case EMIT_1F: diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index d2893c3b9d..f18ad75a47 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -45,6 +45,9 @@ struct r300_winsys { /* PCI ID */ uint32_t pci_id; + /* GB pipe count */ + uint32_t gb_pipes; + /* GART size. */ uint32_t gart_size; diff --git a/src/gallium/drivers/trace/tr_dump.c b/src/gallium/drivers/trace/tr_dump.c index 643587ab42..7e2ccbcfdc 100644 --- a/src/gallium/drivers/trace/tr_dump.c +++ b/src/gallium/drivers/trace/tr_dump.c @@ -351,7 +351,7 @@ void trace_dump_call_begin_locked(const char *klass, const char *method) trace_dump_indent(1); trace_dump_writes("<call no=\'"); trace_dump_writef("%lu", call_no); - trace_dump_writes("\' class =\'"); + trace_dump_writes("\' class=\'"); trace_dump_escape(klass); trace_dump_writes("\' method=\'"); trace_dump_escape(method); |