summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/r300/r300_vs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r300/r300_vs.c')
-rw-r--r--src/gallium/drivers/r300/r300_vs.c126
1 files changed, 111 insertions, 15 deletions
diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c
index c4ed0d712f..68aef70872 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"
@@ -33,6 +34,8 @@
#include "radeon_compiler.h"
+#include "util/u_math.h"
+
/* Convert info about VS output semantics into r300_shader_semantics. */
static void r300_shader_read_vs_outputs(
struct tgsi_shader_info* info,
@@ -88,11 +91,13 @@ 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;
+ boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
+ vs_outputs->bcolor[1] != ATTR_UNUSED;
/* Do the actual vertex_info setup.
*
@@ -119,13 +124,19 @@ static void r300_shader_vap_output_fmt(
/* Colors. */
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
- if (vs_outputs->color[i] != ATTR_UNUSED) {
+ if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) {
hwfmt[1] |= R300_INPUT_CNTL_COLOR;
hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i;
}
}
- /* XXX Back-face colors. */
+ /* Back-face colors. */
+ if (any_bcolor_used) {
+ for (i = 0; i < ATTR_COLOR_COUNT; i++) {
+ hwfmt[1] |= R300_INPUT_CNTL_COLOR;
+ hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i);
+ }
+ }
/* Texture coordinates. */
gen_count = 0;
@@ -146,6 +157,9 @@ static void r300_shader_vap_output_fmt(
/* 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
@@ -155,6 +169,8 @@ static void r300_stream_locations_notcl(
int* stream_loc)
{
int i, tabi = 0, gen_count;
+ boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
+ vs_outputs->bcolor[1] != ATTR_UNUSED;
/* Position. */
stream_loc[tabi++] = 0;
@@ -166,14 +182,14 @@ static void r300_stream_locations_notcl(
/* Colors. */
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
- if (vs_outputs->color[i] != ATTR_UNUSED) {
+ if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) {
stream_loc[tabi++] = 2 + i;
}
}
/* Back-face colors. */
- for (i = 0; i < ATTR_COLOR_COUNT; i++) {
- if (vs_outputs->bcolor[i] != ATTR_UNUSED) {
+ if (any_bcolor_used) {
+ for (i = 0; i < ATTR_COLOR_COUNT; i++) {
stream_loc[tabi++] = 4 + i;
}
}
@@ -181,7 +197,7 @@ static void r300_stream_locations_notcl(
/* Texture coordinates. */
gen_count = 0;
for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
- if (vs_outputs->bcolor[i] != ATTR_UNUSED) {
+ if (vs_outputs->generic[i] != ATTR_UNUSED) {
assert(tabi < 16);
stream_loc[tabi++] = 6 + gen_count;
gen_count++;
@@ -195,8 +211,12 @@ static void r300_stream_locations_notcl(
gen_count++;
}
- /* XXX magic */
- assert(gen_count <= 8);
+ /* WPOS. */
+ if (vs_outputs->wpos != ATTR_UNUSED) {
+ assert(tabi < 16);
+ stream_loc[tabi++] = 6 + gen_count;
+ gen_count++;
+ }
for (; tabi < 16;) {
stream_loc[tabi++] = -1;
@@ -209,6 +229,8 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
struct r300_shader_semantics* outputs = &vs->outputs;
struct tgsi_shader_info* info = &vs->info;
int i, reg = 0;
+ boolean any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED ||
+ outputs->bcolor[1] != ATTR_UNUSED;
/* Fill in the input mapping */
for (i = 0; i < info->num_inputs; i++)
@@ -226,14 +248,30 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
c->code->outputs[outputs->psize] = reg++;
}
+ /* If we're writing back facing colors we need to send
+ * four colors to make front/back face colors selection work.
+ * If the vertex program doesn't write all 4 colors, lets
+ * pretend it does by skipping output index reg so the colors
+ * get written into appropriate output vectors.
+ */
+
/* Colors. */
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
if (outputs->color[i] != ATTR_UNUSED) {
c->code->outputs[outputs->color[i]] = reg++;
+ } else if (any_bcolor_used) {
+ reg++;
}
}
- /* XXX Back-face colors. */
+ /* Back-face colors. */
+ for (i = 0; i < ATTR_COLOR_COUNT; i++) {
+ if (outputs->bcolor[i] != ATTR_UNUSED) {
+ c->code->outputs[outputs->bcolor[i]] = reg++;
+ } else if (any_bcolor_used) {
+ reg++;
+ }
+ }
/* Texture coordinates. */
for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
@@ -246,6 +284,33 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
if (outputs->fog != ATTR_UNUSED) {
c->code->outputs[outputs->fog] = reg++;
}
+
+ /* WPOS. */
+ if (outputs->wpos != ATTR_UNUSED) {
+ c->code->outputs[outputs->wpos] = reg++;
+ }
+}
+
+static void r300_insert_wpos(struct r300_vertex_program_compiler* c,
+ struct r300_shader_semantics* outputs)
+{
+ int i, lastOutput = 0;
+
+ /* Find the max output index. */
+ lastOutput = MAX2(lastOutput, outputs->psize);
+ for (i = 0; i < ATTR_COLOR_COUNT; i++) {
+ lastOutput = MAX2(lastOutput, outputs->color[i]);
+ lastOutput = MAX2(lastOutput, outputs->bcolor[i]);
+ }
+ for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
+ lastOutput = MAX2(lastOutput, outputs->generic[i]);
+ }
+ lastOutput = MAX2(lastOutput, outputs->fog);
+
+ /* Set WPOS after the last output. */
+ lastOutput++;
+ rc_copy_output(&c->Base, 0, lastOutput); /* out[lastOutput] = out[0]; */
+ outputs->wpos = lastOutput;
}
void r300_translate_vertex_shader(struct r300_context* r300,
@@ -256,8 +321,6 @@ void r300_translate_vertex_shader(struct r300_context* r300,
/* Initialize. */
r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
- r300_shader_vap_output_fmt(&vs->outputs, vs->hwfmt);
- r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
/* Setup the compiler */
rc_init(&compiler.Base);
@@ -277,9 +340,15 @@ void r300_translate_vertex_shader(struct r300_context* r300,
r300_tgsi_to_rc(&ttr, vs->state.tokens);
- compiler.RequiredOutputs = ~(~0 << vs->info.num_outputs);
+ compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1));
compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
+ /* Insert the WPOS output. */
+ r300_insert_wpos(&compiler, &vs->outputs);
+
+ r300_shader_vap_output_fmt(vs);
+ r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
+
/* Invoke the compiler */
r3xx_compile_vertex_program(&compiler);
if (compiler.Base.Error) {
@@ -292,3 +361,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;
+}