summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2010-05-26 23:47:27 +0200
committerMarek Olšák <maraeo@gmail.com>2010-05-27 00:08:42 +0200
commit76034aaf655134c71e1ec619085c46251d037720 (patch)
tree59b61e35069a07de4b1e5bfcc3d215b9dbed5ddd /src
parent1345c5bf94dd848bdb601061c7ae654dadc6e542 (diff)
r300g: decouple drawing code and two-sided stencil refvalue fallback
It's now more separate from the rest of the driver and it can be disabled by commenting out just 1 line. Well, I couldn't make the previous version work with SW TCL reliably, that's the reason of this little rework.
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/r300/r300_context.h24
-rw-r--r--src/gallium/drivers/r300/r300_render.c315
-rw-r--r--src/gallium/drivers/r300/r300_state.c20
3 files changed, 154 insertions, 205 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 97b69e7652..e047307e10 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -36,9 +36,9 @@
struct u_upload_mgr;
struct r300_context;
-
struct r300_fragment_shader;
struct r300_vertex_shader;
+struct r300_stencilref_context;
struct r300_atom {
/* List pointers. */
@@ -86,7 +86,7 @@ struct r300_dsa_state {
/* Whether a two-sided stencil is enabled. */
boolean two_sided;
/* Whether a fallback should be used for a two-sided stencil ref value. */
- boolean stencil_ref_bf_fallback;
+ boolean two_sided_stencil_ref;
};
struct r300_rs_state {
@@ -331,21 +331,6 @@ struct r300_context {
/* Parent class */
struct pipe_context context;
- /* Emission of drawing packets. */
- void (*emit_draw_arrays_immediate)(
- struct r300_context *r300,
- unsigned mode, unsigned start, unsigned count);
-
- void (*emit_draw_arrays)(
- struct r300_context *r300,
- unsigned mode, unsigned count);
-
- void (*emit_draw_elements)(
- struct r300_context *r300, struct pipe_resource* indexBuffer,
- unsigned indexSize, unsigned minIndex, unsigned maxIndex,
- unsigned mode, unsigned start, unsigned count);
-
-
/* The interface to the windowing system, etc. */
struct r300_winsys_screen *rws;
/* Screen. */
@@ -354,6 +339,8 @@ struct r300_context {
struct draw_context* draw;
/* Accelerated blit support. */
struct blitter_context* blitter;
+ /* Stencil two-sided reference value fallback. */
+ struct r300_stencilref_context *stencilref_fallback;
/* Vertex buffer for rendering. */
struct pipe_resource* vbo;
@@ -441,9 +428,6 @@ struct r300_context {
uint32_t zbuffer_bpp;
/* Whether rendering is conditional and should be skipped. */
boolean skip_rendering;
- /* Whether the two-sided stencil ref value is different for front and
- * back faces, and fallback should be used for r3xx-r4xx. */
- boolean stencil_ref_bf_fallback;
/* Point sprites texcoord index, 1 bit per texcoord */
int sprite_coord_enable;
/* Whether two-sided color selection is enabled (AKA light_twoside). */
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index c289c3d0e5..cad78a1390 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -157,11 +157,6 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL;
unsigned end_dwords = 0;
- /* Stencil ref fallback. */
- if (r300->stencil_ref_bf_fallback) {
- cs_dwords = cs_dwords * 2 + 10;
- }
-
/* Add dirty state, index offset, and AOS. */
if (first_draw) {
cs_dwords += r300_get_num_dirty_dwords(r300);
@@ -250,7 +245,7 @@ static boolean immd_is_good_idea(struct r300_context *r300,
* after resolving fallback issues (e.g. stencil ref two-sided). *
****************************************************************************/
-static void r500_emit_draw_arrays_immediate(struct r300_context *r300,
+static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
unsigned mode,
unsigned start,
unsigned count)
@@ -340,7 +335,7 @@ static void r500_emit_draw_arrays_immediate(struct r300_context *r300,
}
}
-static void r500_emit_draw_arrays(struct r300_context *r300,
+static void r300_emit_draw_arrays(struct r300_context *r300,
unsigned mode,
unsigned count)
{
@@ -369,7 +364,7 @@ static void r500_emit_draw_arrays(struct r300_context *r300,
END_CS;
}
-static void r500_emit_draw_elements(struct r300_context *r300,
+static void r300_emit_draw_elements(struct r300_context *r300,
struct pipe_resource* indexBuffer,
unsigned indexSize,
unsigned minIndex,
@@ -432,104 +427,6 @@ static void r500_emit_draw_elements(struct r300_context *r300,
END_CS;
}
-/*****************************************************************************
- * The emission of draw packets for r300 which take care of the two-sided *
- * stencil ref fallback and call r500's functions. *
- ****************************************************************************/
-
-/* Set drawing for front faces. */
-static void r300_begin_stencil_ref_fallback(struct r300_context *r300)
-{
- struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
- CS_LOCALS(r300);
-
- BEGIN_CS(2);
- OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode | R300_CULL_BACK);
- END_CS;
-}
-
-/* Set drawing for back faces. */
-static void r300_switch_stencil_ref_side(struct r300_context *r300)
-{
- struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
- struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
- CS_LOCALS(r300);
-
- BEGIN_CS(4);
- OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode | R300_CULL_FRONT);
- OUT_CS_REG(R300_ZB_STENCILREFMASK,
- dsa->stencil_ref_bf | r300->stencil_ref.ref_value[1]);
- END_CS;
-}
-
-/* Restore the original state. */
-static void r300_end_stencil_ref_fallback(struct r300_context *r300)
-{
- struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
- struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
- CS_LOCALS(r300);
-
- BEGIN_CS(4);
- OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode);
- OUT_CS_REG(R300_ZB_STENCILREFMASK,
- dsa->stencil_ref_mask | r300->stencil_ref.ref_value[0]);
- END_CS;
-}
-
-static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
- unsigned mode,
- unsigned start,
- unsigned count)
-{
- if (!r300->stencil_ref_bf_fallback) {
- r500_emit_draw_arrays_immediate(r300, mode, start, count);
- } else {
- r300_begin_stencil_ref_fallback(r300);
- r500_emit_draw_arrays_immediate(r300, mode, start, count);
- r300_switch_stencil_ref_side(r300);
- r500_emit_draw_arrays_immediate(r300, mode, start, count);
- r300_end_stencil_ref_fallback(r300);
- }
-}
-
-static void r300_emit_draw_arrays(struct r300_context *r300,
- unsigned mode,
- unsigned count)
-{
- if (!r300->stencil_ref_bf_fallback) {
- r500_emit_draw_arrays(r300, mode, count);
- } else {
- r300_begin_stencil_ref_fallback(r300);
- r500_emit_draw_arrays(r300, mode, count);
- r300_switch_stencil_ref_side(r300);
- r500_emit_draw_arrays(r300, mode, count);
- r300_end_stencil_ref_fallback(r300);
- }
-}
-
-static void r300_emit_draw_elements(struct r300_context *r300,
- struct pipe_resource* indexBuffer,
- unsigned indexSize,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count)
-{
- if (!r300->stencil_ref_bf_fallback) {
- r500_emit_draw_elements(r300, indexBuffer, indexSize,
- minIndex, maxIndex, mode, start, count);
- } else {
- r300_begin_stencil_ref_fallback(r300);
- r500_emit_draw_elements(r300, indexBuffer, indexSize,
- minIndex, maxIndex, mode, start, count);
- r300_switch_stencil_ref_side(r300);
- r500_emit_draw_elements(r300, indexBuffer, indexSize,
- minIndex, maxIndex, mode, start, count);
- r300_end_stencil_ref_fallback(r300);
- }
-}
-
static void r300_shorten_ubyte_elts(struct r300_context* r300,
struct pipe_resource** elts,
unsigned start,
@@ -638,12 +535,12 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
u_upload_flush(r300->upload_vb);
u_upload_flush(r300->upload_ib);
if (alt_num_verts || count <= 65535) {
- r300->emit_draw_elements(r300, indexBuffer, indexSize,
+ r300_emit_draw_elements(r300, indexBuffer, indexSize,
minIndex, maxIndex, mode, start, count);
} else {
do {
short_count = MIN2(count, 65534);
- r300->emit_draw_elements(r300, indexBuffer, indexSize,
+ r300_emit_draw_elements(r300, indexBuffer, indexSize,
minIndex, maxIndex,
mode, start, short_count);
@@ -697,18 +594,18 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
r300_update_derived_state(r300);
if (immd_is_good_idea(r300, count)) {
- r300->emit_draw_arrays_immediate(r300, mode, start, count);
+ r300_emit_draw_arrays_immediate(r300, mode, start, count);
} else {
/* 9 spare dwords for emit_draw_arrays. */
r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS,
NULL, 9, start, 0, NULL);
if (alt_num_verts || count <= 65535) {
- r300->emit_draw_arrays(r300, mode, count);
+ r300_emit_draw_arrays(r300, mode, count);
} else {
do {
short_count = MIN2(count, 65535);
- r300->emit_draw_arrays(r300, mode, short_count);
+ r300_emit_draw_arrays(r300, mode, short_count);
start += short_count;
count -= short_count;
@@ -945,7 +842,7 @@ static boolean r300_render_set_primitive(struct vbuf_render* render,
return TRUE;
}
-static void r500_render_draw_arrays(struct vbuf_render* render,
+static void r300_render_draw_arrays(struct vbuf_render* render,
unsigned start,
unsigned count)
{
@@ -991,7 +888,7 @@ static void r500_render_draw_arrays(struct vbuf_render* render,
END_CS;
}
-static void r500_render_draw_elements(struct vbuf_render* render,
+static void r300_render_draw_elements(struct vbuf_render* render,
const ushort* indices,
uint count)
{
@@ -1047,40 +944,6 @@ static void r500_render_draw_elements(struct vbuf_render* render,
}
}
-static void r300_render_draw_arrays(struct vbuf_render* render,
- unsigned start,
- unsigned count)
-{
- struct r300_context* r300 = r300_render(render)->r300;
-
- if (!r300->stencil_ref_bf_fallback) {
- r500_render_draw_arrays(render, start, count);
- } else {
- r300_begin_stencil_ref_fallback(r300);
- r500_render_draw_arrays(render, start, count);
- r300_switch_stencil_ref_side(r300);
- r500_render_draw_arrays(render, start, count);
- r300_end_stencil_ref_fallback(r300);
- }
-}
-
-static void r300_render_draw_elements(struct vbuf_render* render,
- const ushort* indices,
- uint count)
-{
- struct r300_context* r300 = r300_render(render)->r300;
-
- if (!r300->stencil_ref_bf_fallback) {
- r500_render_draw_elements(render, indices, count);
- } else {
- r300_begin_stencil_ref_fallback(r300);
- r500_render_draw_elements(render, indices, count);
- r300_switch_stencil_ref_side(r300);
- r500_render_draw_elements(render, indices, count);
- r300_end_stencil_ref_fallback(r300);
- }
-}
-
static void r300_render_destroy(struct vbuf_render* render)
{
FREE(render);
@@ -1101,13 +964,8 @@ static struct vbuf_render* r300_render_create(struct r300_context* r300)
r300render->base.map_vertices = r300_render_map_vertices;
r300render->base.unmap_vertices = r300_render_unmap_vertices;
r300render->base.set_primitive = r300_render_set_primitive;
- if (r300->screen->caps.is_r500) {
- r300render->base.draw_elements = r500_render_draw_elements;
- r300render->base.draw_arrays = r500_render_draw_arrays;
- } else {
- r300render->base.draw_elements = r300_render_draw_elements;
- r300render->base.draw_arrays = r300_render_draw_arrays;
- }
+ r300render->base.draw_elements = r300_render_draw_elements;
+ r300render->base.draw_arrays = r300_render_draw_arrays;
r300render->base.release_vertices = r300_render_release_vertices;
r300render->base.destroy = r300_render_destroy;
@@ -1141,25 +999,150 @@ struct draw_stage* r300_draw_stage(struct r300_context* r300)
return stage;
}
+/****************************************************************************
+ * Two-sided stencil reference value fallback. It's designed to be as much
+ * separate from rest of the driver as possible.
+ ***************************************************************************/
+
+struct r300_stencilref_context {
+ void (*draw_arrays)(struct pipe_context *pipe,
+ unsigned mode, unsigned start, unsigned count);
+
+ void (*draw_range_elements)(
+ struct pipe_context *pipe, struct pipe_resource *indexBuffer,
+ unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex,
+ unsigned mode, unsigned start, unsigned count);
+
+ uint32_t rs_cull_mode;
+ uint32_t zb_stencilrefmask;
+ ubyte ref_value_front;
+};
+
+static boolean r300_stencilref_needed(struct r300_context *r300)
+{
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+
+ return dsa->two_sided_stencil_ref ||
+ (dsa->two_sided &&
+ r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]);
+}
+
+/* Set drawing for front faces. */
+static void r300_stencilref_begin(struct r300_context *r300)
+{
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+ struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+
+ /* Save state. */
+ sr->rs_cull_mode = rs->cull_mode;
+ sr->zb_stencilrefmask = dsa->stencil_ref_mask;
+ sr->ref_value_front = r300->stencil_ref.ref_value[0];
+
+ /* We *cull* pixels, therefore no need to mask out the bits. */
+ rs->cull_mode |= R300_CULL_BACK;
+
+ r300->rs_state.dirty = TRUE;
+}
+
+/* Set drawing for back faces. */
+static void r300_stencilref_switch_side(struct r300_context *r300)
+{
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+ struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+
+ rs->cull_mode = sr->rs_cull_mode | R300_CULL_FRONT;
+ dsa->stencil_ref_mask = dsa->stencil_ref_bf;
+ r300->stencil_ref.ref_value[0] = r300->stencil_ref.ref_value[1];
+
+ r300->rs_state.dirty = TRUE;
+ r300->dsa_state.dirty = TRUE;
+}
+
+/* Restore the original state. */
+static void r300_stencilref_end(struct r300_context *r300)
+{
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+ struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+
+ /* Restore state. */
+ rs->cull_mode = sr->rs_cull_mode;
+ dsa->stencil_ref_mask = sr->zb_stencilrefmask;
+ r300->stencil_ref.ref_value[0] = sr->ref_value_front;
+
+ r300->rs_state.dirty = TRUE;
+ r300->dsa_state.dirty = TRUE;
+}
+
+static void r300_stencilref_draw_arrays(struct pipe_context *pipe, unsigned mode,
+ unsigned start, unsigned count)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+
+ if (!r300_stencilref_needed(r300)) {
+ sr->draw_arrays(pipe, mode, start, count);
+ } else {
+ r300_stencilref_begin(r300);
+ sr->draw_arrays(pipe, mode, start, count);
+ r300_stencilref_switch_side(r300);
+ sr->draw_arrays(pipe, mode, start, count);
+ r300_stencilref_end(r300);
+ }
+}
+
+static void r300_stencilref_draw_range_elements(
+ struct pipe_context *pipe, struct pipe_resource *indexBuffer,
+ unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+
+ if (!r300_stencilref_needed(r300)) {
+ sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
+ minIndex, maxIndex, mode, start, count);
+ } else {
+ r300_stencilref_begin(r300);
+ sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
+ minIndex, maxIndex, mode, start, count);
+ r300_stencilref_switch_side(r300);
+ sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
+ minIndex, maxIndex, mode, start, count);
+ r300_stencilref_end(r300);
+ }
+}
+
+static void r300_plug_in_stencil_ref_fallback(struct r300_context *r300)
+{
+ r300->stencilref_fallback = CALLOC_STRUCT(r300_stencilref_context);
+
+ /* Save original draw functions. */
+ r300->stencilref_fallback->draw_arrays = r300->context.draw_arrays;
+ r300->stencilref_fallback->draw_range_elements = r300->context.draw_range_elements;
+
+ /* Override the draw functions. */
+ r300->context.draw_arrays = r300_stencilref_draw_arrays;
+ r300->context.draw_range_elements = r300_stencilref_draw_range_elements;
+}
+
void r300_init_render_functions(struct r300_context *r300)
{
+ /* Set generic functions. */
+ r300->context.draw_elements = r300_draw_elements;
+
+ /* Set draw functions based on presence of HW TCL. */
if (r300->screen->caps.has_tcl) {
r300->context.draw_arrays = r300_draw_arrays;
- r300->context.draw_elements = r300_draw_elements;
r300->context.draw_range_elements = r300_draw_range_elements;
-
- if (r300->screen->caps.is_r500) {
- r300->emit_draw_arrays_immediate = r500_emit_draw_arrays_immediate;
- r300->emit_draw_arrays = r500_emit_draw_arrays;
- r300->emit_draw_elements = r500_emit_draw_elements;
- } else {
- r300->emit_draw_arrays_immediate = r300_emit_draw_arrays_immediate;
- r300->emit_draw_arrays = r300_emit_draw_arrays;
- r300->emit_draw_elements = r300_emit_draw_elements;
- }
} else {
r300->context.draw_arrays = r300_swtcl_draw_arrays;
- r300->context.draw_elements = r300_draw_elements;
r300->context.draw_range_elements = r300_swtcl_draw_range_elements;
}
+
+ /* Plug in two-sided stencil reference value fallback if needed. */
+ if (!r300->screen->caps.is_r500)
+ r300_plug_in_stencil_ref_fallback(r300);
}
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 46f1653b5b..80346e0c79 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -474,7 +474,7 @@ static void*
if (caps->is_r500) {
dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK;
} else {
- dsa->stencil_ref_bf_fallback =
+ dsa->two_sided_stencil_ref =
(state->stencil[0].valuemask != state->stencil[1].valuemask ||
state->stencil[0].writemask != state->stencil[1].writemask);
}
@@ -497,20 +497,6 @@ static void*
return (void*)dsa;
}
-static void r300_update_stencil_ref_fallback_status(struct r300_context *r300)
-{
- struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
-
- if (r300->screen->caps.is_r500) {
- return;
- }
-
- r300->stencil_ref_bf_fallback =
- dsa->stencil_ref_bf_fallback ||
- (dsa->two_sided &&
- r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]);
-}
-
/* Bind DSA state. */
static void r300_bind_dsa_state(struct pipe_context* pipe,
void* state)
@@ -522,8 +508,6 @@ static void r300_bind_dsa_state(struct pipe_context* pipe,
}
UPDATE_STATE(state, r300->dsa_state);
-
- r300_update_stencil_ref_fallback_status(r300);
}
/* Free DSA state. */
@@ -540,8 +524,6 @@ static void r300_set_stencil_ref(struct pipe_context* pipe,
r300->stencil_ref = *sr;
r300->dsa_state.dirty = TRUE;
-
- r300_update_stencil_ref_fallback_status(r300);
}
/* This switcheroo is needed just because of goddamned MACRO_SWITCH. */