ir_constant_visitor: Handle array access of constant vectors and matrices
authorIan Romanick <ian.d.romanick@intel.com>
Fri, 11 Jun 2010 19:20:12 +0000 (12:20 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 11 Jun 2010 22:43:56 +0000 (15:43 -0700)
ir_constant_expression.cpp

index 8e9e74bb7d889bb5a2222b4edf993974690a65c8..a7c4fe6382e78b1697ab5c94d4cb7ae64b266ffb 100644 (file)
@@ -557,9 +557,57 @@ ir_constant_visitor::visit(ir_dereference_variable *ir)
 void
 ir_constant_visitor::visit(ir_dereference_array *ir)
 {
-   (void) ir;
-   value = NULL;
-   /* FINISHME: Other dereference modes. */
+   ir_constant *array = ir->array->constant_expression_value();
+   ir_constant *idx = ir->array_index->constant_expression_value();
+
+   this->value = NULL;
+
+   if ((array != NULL) && (idx != NULL)) {
+      if (array->type->is_matrix()) {
+        /* Array access of a matrix results in a vector.
+         */
+        const unsigned column = idx->value.u[0];
+
+        const glsl_type *const column_type = array->type->column_type();
+
+        /* Offset in the constant matrix to the first element of the column
+         * to be extracted.
+         */
+        const unsigned mat_idx = column * column_type->vector_elements;
+
+        union {
+           unsigned u[4];
+           float f[4];
+        } data;
+
+        switch (column_type->base_type) {
+        case GLSL_TYPE_UINT:
+        case GLSL_TYPE_INT:
+           for (unsigned i = 0; i < column_type->vector_elements; i++)
+              data.u[i] = array->value.u[mat_idx + i];
+
+           break;
+
+        case GLSL_TYPE_FLOAT:
+           for (unsigned i = 0; i < column_type->vector_elements; i++)
+              data.f[i] = array->value.f[mat_idx + i];
+
+           break;
+
+        default:
+           assert(!"Should not get here.");
+           break;
+        }
+
+        this->value = new ir_constant(column_type, &data);
+      } else if (array->type->is_vector()) {
+        const unsigned component = idx->value.u[0];
+
+        this->value = new ir_constant(array, component);
+      } else {
+        /* FINISHME: Handle access of constant arrays. */
+      }
+   }
 }