glsl: Use the C99 variadic macro syntax.
[mesa.git] / src / glsl / ir_set_program_inouts.cpp
index 8c2bc30d614a96f3192d571717b14b30e746f257..91a8b452683a81d1872bdd43eaadf799b4bdacca 100644 (file)
@@ -26,7 +26,8 @@
  *
  * Sets the InputsRead and OutputsWritten of Mesa programs.
  *
- * Additionally, for fragment shaders, sets the InterpQualifier array.
+ * Additionally, for fragment shaders, sets the InterpQualifier array, the
+ * IsCentroid bitfield, and the UsesDFdy flag.
  *
  * Mesa programs (gl_program, not gl_shader_program) have a set of
  * flags indicating which varyings are read and written.  Computing
@@ -37,7 +38,6 @@
  */
 
 #include "main/core.h" /* for struct gl_program */
-#include "program/hash_table.h"
 #include "ir.h"
 #include "ir_visitor.h"
 #include "glsl_types.h"
@@ -49,25 +49,29 @@ public:
    {
       this->prog = prog;
       this->is_fragment_shader = is_fragment_shader;
-      this->ht = hash_table_ctor(0,
-                                hash_table_pointer_hash,
-                                hash_table_pointer_compare);
    }
    ~ir_set_program_inouts_visitor()
    {
-      hash_table_dtor(this->ht);
    }
 
    virtual ir_visitor_status visit_enter(ir_dereference_array *);
    virtual ir_visitor_status visit_enter(ir_function_signature *);
+   virtual ir_visitor_status visit_enter(ir_expression *);
+   virtual ir_visitor_status visit_enter(ir_discard *);
    virtual ir_visitor_status visit(ir_dereference_variable *);
-   virtual ir_visitor_status visit(ir_variable *);
 
    struct gl_program *prog;
-   struct hash_table *ht;
    bool is_fragment_shader;
 };
 
+static inline bool
+is_shader_inout(ir_variable *var)
+{
+   return var->mode == ir_var_shader_in ||
+          var->mode == ir_var_shader_out ||
+          var->mode == ir_var_system_value;
+}
+
 static void
 mark(struct gl_program *prog, ir_variable *var, int offset, int len,
      bool is_fragment_shader)
@@ -81,17 +85,20 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
     */
 
    for (int i = 0; i < len; i++) {
-      GLbitfield64 bitfield = BITFIELD64_BIT(var->location + offset + i);
-      if (var->mode == ir_var_in) {
+      GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i);
+      if (var->mode == ir_var_shader_in) {
         prog->InputsRead |= bitfield;
          if (is_fragment_shader) {
             gl_fragment_program *fprog = (gl_fragment_program *) prog;
-            fprog->InterpQualifier[var->location + offset + i] =
+            fprog->InterpQualifier[var->location + var->index + offset + i] =
                (glsl_interp_qualifier) var->interpolation;
+            if (var->centroid)
+               fprog->IsCentroid |= bitfield;
          }
       } else if (var->mode == ir_var_system_value) {
          prog->SystemValuesRead |= bitfield;
       } else {
+         assert(var->mode == ir_var_shader_out);
         prog->OutputsWritten |= bitfield;
       }
    }
@@ -101,7 +108,7 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
 ir_visitor_status
 ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
 {
-   if (hash_table_find(this->ht, ir->var) == NULL)
+   if (!is_shader_inout(ir->var))
       return visit_continue;
 
    if (ir->type->is_array()) {
@@ -122,13 +129,13 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
    ir_dereference_variable *deref_var;
    ir_constant *index = ir->array_index->as_constant();
    deref_var = ir->array->as_dereference_variable();
-   ir_variable *var = NULL;
+   ir_variable *var = deref_var ? deref_var->var : NULL;
 
    /* Check that we're dereferencing a shader in or out */
-   if (deref_var)
-      var = (ir_variable *)hash_table_find(this->ht, deref_var->var);
+   if (!var || !is_shader_inout(var))
+      return visit_continue;
 
-   if (index && var) {
+   if (index) {
       int width = 1;
 
       if (deref_var->type->is_array() &&
@@ -144,18 +151,6 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
    return visit_continue;
 }
 
-ir_visitor_status
-ir_set_program_inouts_visitor::visit(ir_variable *ir)
-{
-   if (ir->mode == ir_var_in ||
-       ir->mode == ir_var_out ||
-       ir->mode == ir_var_system_value) {
-      hash_table_insert(this->ht, ir, ir);
-   }
-
-   return visit_continue;
-}
-
 ir_visitor_status
 ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
 {
@@ -166,6 +161,28 @@ ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
    return visit_continue_with_parent;
 }
 
+ir_visitor_status
+ir_set_program_inouts_visitor::visit_enter(ir_expression *ir)
+{
+   if (is_fragment_shader && ir->operation == ir_unop_dFdy) {
+      gl_fragment_program *fprog = (gl_fragment_program *) prog;
+      fprog->UsesDFdy = true;
+   }
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_set_program_inouts_visitor::visit_enter(ir_discard *)
+{
+   /* discards are only allowed in fragment shaders. */
+   assert(is_fragment_shader);
+
+   gl_fragment_program *fprog = (gl_fragment_program *) prog;
+   fprog->UsesKill = true;
+
+   return visit_continue;
+}
+
 void
 do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
                       bool is_fragment_shader)
@@ -176,8 +193,11 @@ do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
    prog->OutputsWritten = 0;
    prog->SystemValuesRead = 0;
    if (is_fragment_shader) {
-      memset(((gl_fragment_program *) prog)->InterpQualifier, 0,
-             sizeof(((gl_fragment_program *) prog)->InterpQualifier));
+      gl_fragment_program *fprog = (gl_fragment_program *) prog;
+      memset(fprog->InterpQualifier, 0, sizeof(fprog->InterpQualifier));
+      fprog->IsCentroid = 0;
+      fprog->UsesDFdy = false;
+      fprog->UsesKill = false;
    }
    visit_list_elements(&v, instructions);
 }