summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/r300/r300_state.c12
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c18
-rw-r--r--src/gallium/drivers/r300/r300_vs.c56
-rw-r--r--src/gallium/drivers/r300/r300_vs.h6
4 files changed, 58 insertions, 34 deletions
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index ad8e210dcd8..affd0b45910 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -556,6 +556,10 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
r300->fs = fs;
r300_pick_fragment_shader(r300);
+ if (r300->vs && r300_vertex_shader_setup_wpos(r300)) {
+ r300->dirty_state |= R300_NEW_VERTEX_FORMAT;
+ }
+
r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS;
}
@@ -974,7 +978,13 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
}
r300->vs = vs;
- r300->dirty_state |= R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS;
+ if (r300->fs) {
+ r300_vertex_shader_setup_wpos(r300);
+ }
+
+ r300->dirty_state |=
+ R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS |
+ R300_NEW_VERTEX_FORMAT;
} else {
draw_flush(r300->draw);
draw_bind_vertex_shader(r300->draw,
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 242716fcccb..2a12a02e18a 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -411,23 +411,13 @@ static void r300_update_rs_block(struct r300_context* r300,
}
/* Rasterize WPOS. */
- if (vs_outputs->wpos != ATTR_UNUSED) {
- /* Always rasterize if it's written by the VS,
- * otherwise it locks up. */
+ /* If the FS doesn't need it, it's not written by the VS. */
+ if (fs_inputs->wpos != ATTR_UNUSED) {
rX00_rs_tex(rs, tex_count, tex_count, FALSE);
+ rX00_rs_tex_write(rs, tex_count, fp_offset);
- /* Write it to the FS input register if it's used by the FS. */
- if (fs_inputs->wpos != ATTR_UNUSED) {
- rX00_rs_tex_write(rs, tex_count, fp_offset);
- fp_offset++;
- }
+ fp_offset++;
tex_count++;
- } else {
- /* Skip the FS input register, leave it uninitialized. */
- /* If we try to set it to (0,0,0,1), it will lock up. */
- if (fs_inputs->wpos != ATTR_UNUSED) {
- fp_offset++;
- }
}
/* Rasterize at least one color, or bad things happen. */
diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c
index 57531fc554f..3512a6dc760 100644
--- a/src/gallium/drivers/r300/r300_vs.c
+++ b/src/gallium/drivers/r300/r300_vs.c
@@ -22,6 +22,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "r300_vs.h"
+#include "r300_fs.h"
#include "r300_context.h"
#include "r300_screen.h"
@@ -90,10 +91,10 @@ static void r300_shader_read_vs_outputs(
}
}
-static void r300_shader_vap_output_fmt(
- struct r300_shader_semantics* vs_outputs,
- uint* hwfmt)
+static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs)
{
+ struct r300_shader_semantics* vs_outputs = &vs->outputs;
+ uint32_t* hwfmt = vs->hwfmt;
int i, gen_count;
/* Do the actual vertex_info setup.
@@ -146,15 +147,11 @@ static void r300_shader_vap_output_fmt(
gen_count++;
}
- /* WPOS. */
- if (vs_outputs->wpos != ATTR_UNUSED) {
- hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count);
- hwfmt[3] |= (4 << (3 * gen_count));
- gen_count++;
- }
-
/* XXX magic */
assert(gen_count <= 8);
+
+ /* WPOS. */
+ vs->wpos_tex_output = gen_count;
}
/* Sets up stream mapping to equivalent VS outputs if TCL is bypassed
@@ -211,9 +208,6 @@ static void r300_stream_locations_notcl(
gen_count++;
}
- /* XXX magic */
- assert(gen_count <= 8);
-
for (; tabi < 16;) {
stream_loc[tabi++] = -1;
}
@@ -296,7 +290,6 @@ void r300_translate_vertex_shader(struct r300_context* r300,
{
struct r300_vertex_program_compiler compiler;
struct tgsi_to_rc ttr;
- boolean use_wpos = TRUE;
/* Initialize. */
r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
@@ -319,15 +312,13 @@ void r300_translate_vertex_shader(struct r300_context* r300,
r300_tgsi_to_rc(&ttr, vs->state.tokens);
- compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+use_wpos));
+ compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1));
compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
/* Insert the WPOS output. */
- if (use_wpos) {
- r300_insert_wpos(&compiler, &vs->outputs);
- }
+ r300_insert_wpos(&compiler, &vs->outputs);
- r300_shader_vap_output_fmt(&vs->outputs, vs->hwfmt);
+ r300_shader_vap_output_fmt(vs);
r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
/* Invoke the compiler */
@@ -342,3 +333,30 @@ void r300_translate_vertex_shader(struct r300_context* r300,
rc_destroy(&compiler.Base);
vs->translated = TRUE;
}
+
+boolean r300_vertex_shader_setup_wpos(struct r300_context* r300)
+{
+ struct r300_vertex_shader* vs = r300->vs;
+ int tex_output = r300->vs->wpos_tex_output;
+ uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output;
+ uint32_t* hwfmt = vs->hwfmt;
+
+ if (r300->fs->inputs.wpos != ATTR_UNUSED) {
+ /* Enable WPOS in VAP. */
+ if (!(hwfmt[1] & tex_fmt)) {
+ hwfmt[1] |= tex_fmt;
+ hwfmt[3] |= (4 << (3 * tex_output));
+
+ assert(tex_output < 8);
+ return TRUE;
+ }
+ } else {
+ /* Disable WPOS in VAP. */
+ if (hwfmt[1] & tex_fmt) {
+ hwfmt[1] &= ~tex_fmt;
+ hwfmt[3] &= ~(4 << (3 * tex_output));
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h
index 67e9db5366f..18cfeee3cd4 100644
--- a/src/gallium/drivers/r300/r300_vs.h
+++ b/src/gallium/drivers/r300/r300_vs.h
@@ -43,6 +43,9 @@ struct r300_vertex_shader {
/* Stream locations for SWTCL or if TCL is bypassed. */
int stream_loc_notcl[16];
+ /* Output stream location for WPOS. */
+ int wpos_tex_output;
+
/* Has this shader been translated yet? */
boolean translated;
@@ -53,4 +56,7 @@ struct r300_vertex_shader {
void r300_translate_vertex_shader(struct r300_context* r300,
struct r300_vertex_shader* vs);
+/* Return TRUE if VAP (hwfmt) needs to be re-emitted. */
+boolean r300_vertex_shader_setup_wpos(struct r300_context* r300);
+
#endif /* R300_VS_H */