summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r300
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2010-01-17 19:21:03 +0100
committerCorbin Simpson <[email protected]>2010-01-18 02:35:08 -0800
commit673ae6266ebf66145bf2bd7d37965f3fe60371d5 (patch)
tree1c273cd6fac418e25b6717ecc825b3df78bc4d54 /src/gallium/drivers/r300
parentd3d41cbc3504536c2d2dfa2faaae86b2ae5eb670 (diff)
r300g: fix polygon offset
As per classic r300. Not sure why glean/polygonOffset still fails, but we do emit the same register values as in classic.
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r--src/gallium/drivers/r300/r300_context.h12
-rw-r--r--src/gallium/drivers/r300/r300_emit.c30
-rw-r--r--src/gallium/drivers/r300/r300_state.c26
3 files changed, 54 insertions, 14 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index c65d23823c8..5e33dc042ac 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -87,10 +87,10 @@ struct r300_rs_state {
uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */
uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */
uint32_t line_control; /* R300_GA_LINE_CNTL: 0x4234 */
- uint32_t depth_scale_front; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */
- uint32_t depth_offset_front;/* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */
- uint32_t depth_scale_back; /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */
- uint32_t depth_offset_back; /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */
+ float depth_scale; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */
+ /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */
+ float depth_offset; /* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */
+ /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */
uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */
uint32_t cull_mode; /* R300_SU_CULL_MODE: 0x42b8 */
uint32_t line_stipple_config; /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */
@@ -326,6 +326,10 @@ struct r300_context {
uint32_t dirty_hw;
/* Whether the TCL engine should be in bypass mode. */
boolean tcl_bypass;
+ /* Whether polygon offset is enabled. */
+ boolean polygon_offset_enabled;
+ /* Z buffer bit depth. */
+ uint32_t zbuffer_bpp;
};
/* Convenience cast wrapper. */
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 11bd3346c79..2ea9fab015d 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -584,19 +584,37 @@ void r300_emit_query_end(struct r300_context* r300)
void r300_emit_rs_state(struct r300_context* r300, void* state)
{
struct r300_rs_state* rs = (struct r300_rs_state*)state;
+ float scale, offset;
CS_LOCALS(r300);
- BEGIN_CS(22);
+ BEGIN_CS(18 + (rs->polygon_offset_enable ? 5 : 0));
OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status);
OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size);
OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2);
OUT_CS(rs->point_minmax);
OUT_CS(rs->line_control);
- OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 6);
- OUT_CS(rs->depth_scale_front);
- OUT_CS(rs->depth_offset_front);
- OUT_CS(rs->depth_scale_back);
- OUT_CS(rs->depth_offset_back);
+
+ if (rs->polygon_offset_enable) {
+ scale = rs->depth_scale * 12;
+ offset = rs->depth_offset;
+
+ switch (r300->zbuffer_bpp) {
+ case 16:
+ offset *= 4;
+ break;
+ case 24:
+ offset *= 2;
+ break;
+ }
+
+ OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4);
+ OUT_CS_32F(scale);
+ OUT_CS_32F(offset);
+ OUT_CS_32F(scale);
+ OUT_CS_32F(offset);
+ }
+
+ OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_ENABLE, 2);
OUT_CS(rs->polygon_offset_enable);
OUT_CS(rs->cull_mode);
OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config);
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 609b910e12d..e2ec0bc5bd2 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -486,6 +486,7 @@ static void
const struct pipe_framebuffer_state* state)
{
struct r300_context* r300 = r300_context(pipe);
+ uint32_t zbuffer_bpp = 0;
if (r300->draw) {
draw_flush(r300->draw);
@@ -499,6 +500,23 @@ static void
r300->blend_state.dirty = TRUE;
r300->dsa_state.dirty = TRUE;
r300->scissor_state.dirty = TRUE;
+
+ /* Polyfon offset depends on the zbuffer bit depth. */
+ if (state->zsbuf && r300->polygon_offset_enabled) {
+ switch (util_format_get_blocksize(state->zsbuf->texture->format)) {
+ case 2:
+ zbuffer_bpp = 16;
+ break;
+ case 4:
+ zbuffer_bpp = 24;
+ break;
+ }
+
+ if (r300->zbuffer_bpp != zbuffer_bpp) {
+ r300->zbuffer_bpp = zbuffer_bpp;
+ r300->rs_state.dirty = TRUE;
+ }
+ }
}
/* Create fragment shader state. */
@@ -654,10 +672,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
}
if (rs->polygon_offset_enable) {
- rs->depth_offset_front = rs->depth_offset_back =
- fui(state->offset_units);
- rs->depth_scale_front = rs->depth_scale_back =
- fui(state->offset_scale);
+ rs->depth_offset = state->offset_units;
+ rs->depth_scale = state->offset_scale;
}
if (state->line_stipple_enable) {
@@ -691,8 +707,10 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
if (rs) {
r300->tcl_bypass = rs->rs.bypass_vs_clip_and_viewport;
+ r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw;
} else {
r300->tcl_bypass = FALSE;
+ r300->polygon_offset_enabled = FALSE;
}
r300->rs_state.state = rs;