summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-06-27 20:36:41 -0700
committerEric Anholt <[email protected]>2010-06-28 11:14:47 -0700
commitbd3b835e7c32e093f91f636330fd93b3dedd8362 (patch)
tree0dca01f32c2a542006710c1a1b08ccb09850c5dc /src/mesa
parent81b7b79c472cbc15cb044656bd37b101a941f358 (diff)
glsl2: Add support for some builtin matrices.
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/shader/ir_to_mesa.cpp86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp
index af5237f697c..a0217bf8d92 100644
--- a/src/mesa/shader/ir_to_mesa.cpp
+++ b/src/mesa/shader/ir_to_mesa.cpp
@@ -1,4 +1,6 @@
/*
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
* Copyright © 2010 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -760,6 +762,86 @@ ir_to_mesa_visitor::visit(ir_swizzle *ir)
this->result = src_reg;
}
+static temp_entry *
+get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var)
+{
+ /*
+ * NOTE: The ARB_vertex_program extension specified that matrices get
+ * loaded in registers in row-major order. With GLSL, we want column-
+ * major order. So, we need to transpose all matrices here...
+ */
+ static const struct {
+ const char *name;
+ int matrix;
+ int modifier;
+ } matrices[] = {
+ { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 },
+ { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 },
+ { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 },
+ { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
+ { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+ };
+ unsigned int i;
+ temp_entry *entry;
+
+ /* C++ gets angry when we try to use an int as a gl_state_index, so we use
+ * ints for gl_state_index. Make sure they're compatible.
+ */
+ assert(sizeof(gl_state_index) == sizeof(int));
+
+ 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];
+
+ 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;
+ }
+
+ entry = new(mem_ctx) temp_entry(var,
+ PROGRAM_STATE_VAR,
+ base_pos);
+
+ return entry;
+ }
+ }
+
+ return NULL;
+}
+
void
ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
{
@@ -771,6 +853,10 @@ 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);
+ if (entry)
+ break;
+
/* FINISHME: Fix up uniform name for arrays and things */
assert(ir->var->type->gl_type != 0 &&
ir->var->type->gl_type != GL_INVALID_ENUM);