summaryrefslogtreecommitdiff
path: root/src/gallium/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/i965simple/brw_surface.c4
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h1
-rw-r--r--src/gallium/drivers/nv50/nv50_state_validate.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c190
-rw-r--r--src/gallium/drivers/r300/r300_chipset.c11
-rw-r--r--src/gallium/drivers/r300/r300_chipset.h4
-rw-r--r--src/gallium/drivers/r300/r300_context.c24
-rw-r--r--src/gallium/drivers/r300/r300_context.h32
-rw-r--r--src/gallium/drivers/r300/r300_emit.c79
-rw-r--r--src/gallium/drivers/r300/r300_query.c76
-rw-r--r--src/gallium/drivers/r300/r300_query.h7
-rw-r--r--src/gallium/drivers/r300/r300_reg.h4
-rw-r--r--src/gallium/drivers/r300/r300_screen.c1
-rw-r--r--src/gallium/drivers/r300/r300_state.c3
-rw-r--r--src/gallium/drivers/r300/r300_state_inlines.h19
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h3
-rw-r--r--src/gallium/drivers/trace/tr_dump.c2
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);