Add some variable declaration qualifier tests
[mesa.git] / builtin_function.cpp
index ec1b54a2dd54d7ed2610ad286225c0e24bd368c3..8e7e1164b8c469920e3aff4560eda78dcd62b4da 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <stdlib.h>
+#include <math.h>
 #include "glsl_symbol_table.h"
 #include "glsl_parser_extras.h"
 #include "glsl_types.h"
@@ -60,6 +61,40 @@ generate_binop(exec_list *instructions,
    instructions->push_tail(inst);
 }
 
+static void
+generate_radians(exec_list *instructions,
+                ir_variable **declarations,
+                const glsl_type *type)
+{
+   ir_dereference *const retval = new ir_dereference(declarations[16]);
+   ir_dereference *const arg = new ir_dereference(declarations[0]);
+   ir_rvalue *result;
+
+   result = new ir_expression(ir_binop_mul, type,
+                             arg,
+                             new ir_constant((float)(M_PI / 180.0)));
+
+   ir_instruction *inst = new ir_assignment(retval, result, NULL);
+   instructions->push_tail(inst);
+}
+
+static void
+generate_degrees(exec_list *instructions,
+                ir_variable **declarations,
+                const glsl_type *type)
+{
+   ir_dereference *const retval = new ir_dereference(declarations[16]);
+   ir_dereference *const arg = new ir_dereference(declarations[0]);
+   ir_rvalue *result;
+
+   result = new ir_expression(ir_binop_mul, type,
+                             arg,
+                             new ir_constant((float)(180.0 / M_PI)));
+
+   ir_instruction *inst = new ir_assignment(retval, result, NULL);
+   instructions->push_tail(inst);
+}
+
 static void
 generate_exp(exec_list *instructions,
             ir_variable **declarations,
@@ -76,6 +111,22 @@ generate_log(exec_list *instructions,
    generate_unop(instructions, declarations, type, ir_unop_log);
 }
 
+static void
+generate_exp2(exec_list *instructions,
+             ir_variable **declarations,
+             const glsl_type *type)
+{
+   generate_unop(instructions, declarations, type, ir_unop_exp2);
+}
+
+static void
+generate_log2(exec_list *instructions,
+             ir_variable **declarations,
+             const glsl_type *type)
+{
+   generate_unop(instructions, declarations, type, ir_unop_log2);
+}
+
 static void
 generate_rsq(exec_list *instructions,
               ir_variable **declarations,
@@ -84,6 +135,14 @@ generate_rsq(exec_list *instructions,
    generate_unop(instructions, declarations, type, ir_unop_rsq);
 }
 
+static void
+generate_sqrt(exec_list *instructions,
+              ir_variable **declarations,
+              const glsl_type *type)
+{
+   generate_unop(instructions, declarations, type, ir_unop_sqrt);
+}
+
 static void
 generate_abs(exec_list *instructions,
             ir_variable **declarations,
@@ -149,6 +208,7 @@ generate_function_instance(ir_function *f,
                           void (*generate)(exec_list *instructions,
                                            ir_variable **declarations,
                                            const glsl_type *type),
+                          const glsl_type *ret_type,
                           const glsl_type *type)
 {
    ir_variable *declarations[17];
@@ -168,15 +228,17 @@ generate_function_instance(ir_function *f,
    for (i = 0; i < n_args; i++) {
       ir_variable *var = new ir_variable(type, arg_names[i]);
 
+      var = new ir_variable(type, arg_names[i]);
       var->mode = ir_var_in;
       sig->parameters.push_tail(var);
 
       var = new ir_variable(type, arg_names[i]);
-
+      var->mode = ir_var_in;
+      instructions->push_tail(var);
       declarations[i] = var;
    }
 
-   ir_variable *retval = new ir_variable(type, "__retval");
+   ir_variable *retval = new ir_variable(ret_type, "__retval");
    instructions->push_tail(retval);
 
    declarations[16] = retval;
@@ -193,6 +255,7 @@ make_gentype_function(glsl_symbol_table *symtab, exec_list *instructions,
                                       const glsl_type *type))
 {
    ir_function *const f = new ir_function(name);
+   const glsl_type *float_type = glsl_type::float_type;
    const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
    const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
    const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);
@@ -201,20 +264,103 @@ make_gentype_function(glsl_symbol_table *symtab, exec_list *instructions,
    assert(added);
 
    generate_function_instance(f, name, instructions, n_args, generate,
-                             glsl_type::float_type);
+                             float_type, float_type);
    generate_function_instance(f, name, instructions, n_args, generate,
-                             vec2_type);
+                             vec2_type, vec2_type);
    generate_function_instance(f, name, instructions, n_args, generate,
-                             vec3_type);
+                             vec3_type, vec3_type);
    generate_function_instance(f, name, instructions, n_args, generate,
-                             vec4_type);
+                             vec4_type, vec4_type);
+}
+
+static void
+generate_length(exec_list *instructions,
+               ir_variable **declarations,
+               const glsl_type *type)
+{
+   ir_dereference *const retval = new ir_dereference(declarations[16]);
+   ir_dereference *const arg = new ir_dereference(declarations[0]);
+   ir_rvalue *result, *temp;
+
+   (void)type;
+
+   /* FINISHME: implement the abs(arg) variant for length(float f) */
+
+   temp = new ir_expression(ir_binop_dot, glsl_type::float_type, arg, arg);
+   result = new ir_expression(ir_unop_sqrt, glsl_type::float_type, temp, NULL);
+
+   ir_instruction *inst = new ir_assignment(retval, result, NULL);
+   instructions->push_tail(inst);
+}
+
+void
+generate_length_functions(glsl_symbol_table *symtab, exec_list *instructions)
+{
+   const char *name = "length";
+   ir_function *const f = new ir_function(name);
+   const glsl_type *float_type = glsl_type::float_type;
+   const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
+   const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
+   const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);
+
+   bool added = symtab->add_function(name, f);
+   assert(added);
+
+   generate_function_instance(f, name, instructions, 1, generate_length,
+                             float_type, float_type);
+   generate_function_instance(f, name, instructions, 1, generate_length,
+                             float_type, vec2_type);
+   generate_function_instance(f, name, instructions, 1, generate_length,
+                             float_type, vec3_type);
+   generate_function_instance(f, name, instructions, 1, generate_length,
+                             float_type, vec4_type);
+}
+
+static void
+generate_dot(exec_list *instructions,
+               ir_variable **declarations,
+               const glsl_type *type)
+{
+   ir_dereference *const retval = new ir_dereference(declarations[16]);
+   ir_dereference *const arg = new ir_dereference(declarations[0]);
+   ir_rvalue *result;
+
+   (void)type;
+
+   result = new ir_expression(ir_binop_dot, glsl_type::float_type, arg, arg);
+
+   ir_instruction *inst = new ir_assignment(retval, result, NULL);
+   instructions->push_tail(inst);
+}
+
+void
+generate_dot_functions(glsl_symbol_table *symtab, exec_list *instructions)
+{
+   const char *name = "dot";
+   ir_function *const f = new ir_function(name);
+   const glsl_type *float_type = glsl_type::float_type;
+   const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
+   const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
+   const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);
+
+   bool added = symtab->add_function(name, f);
+   assert(added);
+
+   generate_function_instance(f, name, instructions, 1, generate_dot,
+                             float_type, float_type);
+   generate_function_instance(f, name, instructions, 1, generate_dot,
+                             float_type, vec2_type);
+   generate_function_instance(f, name, instructions, 1, generate_dot,
+                             float_type, vec3_type);
+   generate_function_instance(f, name, instructions, 1, generate_dot,
+                             float_type, vec4_type);
 }
 
 void
 generate_110_functions(glsl_symbol_table *symtab, exec_list *instructions)
 {
-   /* FINISHME: radians() */
-   /* FINISHME: degrees() */
+   make_gentype_function(symtab, instructions, "radians", 1, generate_radians);
+   make_gentype_function(symtab, instructions, "degrees", 1, generate_degrees);
    /* FINISHME: sin() */
    /* FINISHME: cos() */
    /* FINISHME: tan() */
@@ -225,9 +371,9 @@ generate_110_functions(glsl_symbol_table *symtab, exec_list *instructions)
    make_gentype_function(symtab, instructions, "pow", 2, generate_pow);
    make_gentype_function(symtab, instructions, "exp", 1, generate_exp);
    make_gentype_function(symtab, instructions, "log", 1, generate_log);
-   /* FINISHME: exp2() */
-   /* FINISHME: log2() */
-   /* FINISHME: sqrt() */
+   make_gentype_function(symtab, instructions, "exp2", 1, generate_exp2);
+   make_gentype_function(symtab, instructions, "log2", 1, generate_log2);
+   make_gentype_function(symtab, instructions, "sqrt", 1, generate_sqrt);
    make_gentype_function(symtab, instructions, "inversesqrt", 1, generate_rsq);
    make_gentype_function(symtab, instructions, "abs", 1, generate_abs);
    /* FINISHME: sign() */
@@ -250,9 +396,9 @@ generate_110_functions(glsl_symbol_table *symtab, exec_list *instructions)
    /* FINISHME: smoothstep() */
    /* FINISHME: floor() */
    /* FINISHME: step() */
-   /* FINISHME: length() */
+   generate_length_functions(symtab, instructions);
    /* FINISHME: distance() */
-   /* FINISHME: dot() */
+   generate_dot_functions(symtab, instructions);
    /* FINISHME: cross() */
    /* FINISHME: normalize() */
    /* FINISHME: ftransform() */