diff options
author | Eric Anholt <[email protected]> | 2010-07-07 11:39:48 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-07-07 11:51:36 -0700 |
commit | 76101f7c0468c7f346b1a8d6b824fc8914a17bd1 (patch) | |
tree | f82bb3950dd0a573b97b94bd2a895c6ecbcd05bb /src/mesa/shader/ir_to_mesa.cpp | |
parent | 8bb15c1ed55eb71533d2af94a6afbf01e3d23610 (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.cpp | 103 |
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 d1796920725..21b01edefd4 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. */ |