summaryrefslogtreecommitdiff
path: root/src/mesa/shader/ir_to_mesa.cpp
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-07-07 11:39:48 -0700
committerEric Anholt <eric@anholt.net>2010-07-07 11:51:36 -0700
commit76101f7c0468c7f346b1a8d6b824fc8914a17bd1 (patch)
treef82bb3950dd0a573b97b94bd2a895c6ecbcd05bb /src/mesa/shader/ir_to_mesa.cpp
parent8bb15c1ed55eb71533d2af94a6afbf01e3d23610 (diff)
ir_to_mesa: Add support for gl_TextureMatrix access.
Fixes glsl-vs-texturematrix-1, and glsl-vs-texturematrix-2 on swrast.
Diffstat (limited to 'src/mesa/shader/ir_to_mesa.cpp')
-rw-r--r--src/mesa/shader/ir_to_mesa.cpp103
1 files changed, 84 insertions, 19 deletions
diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp
index d179692072..21b01edefd 100644
--- a/src/mesa/shader/ir_to_mesa.cpp
+++ b/src/mesa/shader/ir_to_mesa.cpp
@@ -869,8 +869,34 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir)
this->result = src_reg;
}
+static int
+add_matrix_ref(struct gl_program *prog, int *tokens)
+{
+ int base_pos = -1;
+ int i;
+
+ /* Add a ref for each column. It looks like the reason we do
+ * it this way is that _mesa_add_state_reference doesn't work
+ * for things that aren't vec4s, so the tokens[2]/tokens[3]
+ * range has to be equal.
+ */
+ for (i = 0; i < 4; i++) {
+ tokens[2] = i;
+ tokens[3] = i;
+ int pos = _mesa_add_state_reference(prog->Parameters,
+ (gl_state_index *)tokens);
+ if (base_pos == -1)
+ base_pos = pos;
+ else
+ assert(base_pos + i == pos);
+ }
+
+ return base_pos;
+}
+
static temp_entry *
-get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var)
+get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var,
+ ir_rvalue *array_index)
{
/*
* NOTE: The ARB_vertex_program extension specified that matrices get
@@ -915,28 +941,31 @@ get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var)
for (i = 0; i < Elements(matrices); i++) {
if (strcmp(var->name, matrices[i].name) == 0) {
- int j;
- int last_pos = -1, base_pos = -1;
int tokens[STATE_LENGTH];
+ int base_pos = -1;
tokens[0] = matrices[i].matrix;
- tokens[1] = 0; /* array index! */
tokens[4] = matrices[i].modifier;
-
- /* Add a ref for each column. It looks like the reason we do
- * it this way is that _mesa_add_state_reference doesn't work
- * for things that aren't vec4s, so the tokens[2]/tokens[3]
- * range has to be equal.
- */
- for (j = 0; j < 4; j++) {
- tokens[2] = j;
- tokens[3] = j;
- int pos = _mesa_add_state_reference(prog->Parameters,
- (gl_state_index *)tokens);
- assert(last_pos == -1 || last_pos == base_pos + j);
- if (base_pos == -1)
- base_pos = pos;
+ if (matrices[i].matrix == STATE_TEXTURE_MATRIX) {
+ ir_constant *index = array_index->constant_expression_value();
+ if (index) {
+ tokens[1] = index->value.i[0];
+ base_pos = add_matrix_ref(prog, tokens);
+ } else {
+ for (i = 0; i < var->type->length; i++) {
+ tokens[1] = i;
+ int pos = add_matrix_ref(prog, tokens);
+ if (base_pos == -1)
+ base_pos = pos;
+ else
+ assert(base_pos + (int)i * 4 == pos);
+ }
+ }
+ } else {
+ tokens[1] = 0; /* unused array index */
+ base_pos = add_matrix_ref(prog, tokens);
}
+ tokens[4] = matrices[i].modifier;
entry = new(mem_ctx) temp_entry(var,
PROGRAM_STATE_VAR,
@@ -959,7 +988,8 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
if (!entry) {
switch (ir->var->mode) {
case ir_var_uniform:
- entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, ir->var);
+ entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, ir->var,
+ NULL);
if (entry)
break;
@@ -1057,9 +1087,44 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
{
ir_constant *index;
ir_to_mesa_src_reg src_reg;
+ ir_dereference_variable *deref_var = ir->array->as_dereference_variable();
index = ir->array_index->constant_expression_value();
+ if (deref_var && strncmp(deref_var->var->name,
+ "gl_TextureMatrix",
+ strlen("gl_TextureMatrix")) == 0) {
+ ir_to_mesa_src_reg src_reg;
+ struct temp_entry *entry;
+
+ entry = get_builtin_matrix_ref(this->mem_ctx, this->prog, deref_var->var,
+ ir->array_index);
+ assert(entry);
+
+ src_reg.file = entry->file;
+ src_reg.index = entry->index;
+ src_reg.swizzle = swizzle_for_size(ir->type->vector_elements);
+ src_reg.negate = 0;
+
+ if (index) {
+ src_reg.reladdr = GL_FALSE;
+ } else {
+ ir_to_mesa_src_reg index_reg = get_temp(glsl_type::float_type);
+
+ ir->array_index->accept(this);
+ ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+ ir_to_mesa_dst_reg_from_src(index_reg),
+ this->result, src_reg_for_float(4.0));
+
+ src_reg.reladdr = true;
+ ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
+ index_reg);
+ }
+
+ this->result = src_reg;
+ return;
+ }
+
/* By the time we make it to this stage, matrices should be broken down
* to vectors.
*/