glsl: Distinguish between no interpolation qualifier and 'smooth'
[profile/ivi/mesa.git] / src / glsl / ir.h
index 3ea7301..0c0cccb 100644 (file)
 #ifndef IR_H
 #define IR_H
 
-#include <cstdio>
-#include <cstdlib>
-
-extern "C" {
-#include <talloc.h>
-}
+#include <stdio.h>
+#include <stdlib.h>
 
+#include "ralloc.h"
+#include "glsl_types.h"
 #include "list.h"
 #include "ir_visitor.h"
 #include "ir_hierarchical_visitor.h"
+#include "main/mtypes.h"
 
 /**
  * \defgroup IR Intermediate representation nodes
@@ -121,6 +120,7 @@ public:
    virtual class ir_if *                as_if()               { return NULL; }
    virtual class ir_swizzle *           as_swizzle()          { return NULL; }
    virtual class ir_constant *          as_constant()         { return NULL; }
+   virtual class ir_discard *           as_discard()          { return NULL; }
    /*@}*/
 
 protected:
@@ -143,7 +143,9 @@ public:
       return this;
    }
 
-   virtual bool is_lvalue()
+   ir_rvalue *as_rvalue_to_saturate();
+
+   virtual bool is_lvalue() const
    {
       return false;
    }
@@ -151,7 +153,7 @@ public:
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
-   virtual ir_variable *variable_referenced()
+   virtual ir_variable *variable_referenced() const
    {
       return NULL;
    }
@@ -179,7 +181,7 @@ public:
     * for vector and scalar types that have all elements set to the value
     * zero (or \c false for booleans).
     *
-    * \sa ir_constant::has_value, ir_rvalue::is_one
+    * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one
     */
    virtual bool is_zero() const;
 
@@ -191,10 +193,22 @@ public:
     * for vector and scalar types that have all elements set to the value
     * one (or \c true for booleans).
     *
-    * \sa ir_constant::has_value, ir_rvalue::is_zero
+    * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one
     */
    virtual bool is_one() const;
 
+   /**
+    * Determine if an r-value has the value negative one
+    *
+    * The base implementation of this function always returns \c false.  The
+    * \c ir_constant class over-rides this function to return \c true \b only
+    * for vector and scalar types that have all elements set to the value
+    * negative one.  For boolean times, the result is always \c false.
+    *
+    * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one
+    */
+   virtual bool is_negative_one() const;
+
 protected:
    ir_rvalue();
 };
@@ -209,15 +223,40 @@ enum ir_variable_mode {
    ir_var_in,
    ir_var_out,
    ir_var_inout,
+   ir_var_const_in,    /**< "in" param that must be a constant expression */
+   ir_var_system_value, /**< Ex: front-face, instance-id, etc. */
    ir_var_temporary    /**< Temporary variable generated during compilation. */
 };
 
-enum ir_variable_interpolation {
-   ir_var_smooth = 0,
-   ir_var_flat,
-   ir_var_noperspective
+/**
+ * \brief Layout qualifiers for gl_FragDepth.
+ *
+ * The AMD/ARB_conservative_depth extensions allow gl_FragDepth to be redeclared
+ * with a layout qualifier.
+ */
+enum ir_depth_layout {
+    ir_depth_layout_none, /**< No depth layout is specified. */
+    ir_depth_layout_any,
+    ir_depth_layout_greater,
+    ir_depth_layout_less,
+    ir_depth_layout_unchanged
 };
 
+/**
+ * \brief Convert depth layout qualifier to string.
+ */
+const char*
+depth_layout_string(ir_depth_layout layout);
+
+/**
+ * Description of built-in state associated with a uniform
+ *
+ * \sa ir_variable::state_slots
+ */
+struct ir_state_slot {
+   int tokens[5];
+   int swizzle;
+};
 
 class ir_variable : public ir_instruction {
 public:
@@ -244,19 +283,15 @@ public:
     * \return The string that would be used in a shader to specify \c
     * mode will be returned.
     *
+    * This function is used to generate error messages of the form "shader
+    * uses %s interpolation qualifier", so in the case where there is no
+    * interpolation qualifier, it returns "no".
+    *
     * This function should only be used on a shader input or output variable.
     */
    const char *interpolation_string() const;
 
    /**
-    * Calculate the number of slots required to hold this variable
-    *
-    * This is used to determine how many uniform or varying locations a variable
-    * occupies.  The count is in units of floating point components.
-    */
-   unsigned component_slots() const;
-
-   /**
     * Delcared name of the variable
     */
    const char *name;
@@ -279,6 +314,15 @@ public:
    unsigned invariant:1;
 
    /**
+    * Has this variable been used for reading or writing?
+    *
+    * Several GLSL semantic checks require knowledge of whether or not a
+    * variable has been used.  For example, it is an error to redeclare a
+    * variable as invariant after it has been used.
+    */
+   unsigned used:1;
+
+   /**
     * Storage class of the variable.
     *
     * \sa ir_variable_mode
@@ -293,14 +337,6 @@ public:
    unsigned interpolation:2;
 
    /**
-    * Flag that the whole array is assignable
-    *
-    * In GLSL 1.20 and later whole arrays are assignable (and comparable for
-    * equality).  This flag enables this behavior.
-    */
-   unsigned array_lvalue:1;
-
-   /**
     * \name ARB_fragment_coord_conventions
     * @{
     */
@@ -309,6 +345,14 @@ public:
    /*@}*/
 
    /**
+    * \brief Layout qualifier for gl_FragDepth.
+    *
+    * This is not equal to \c ir_depth_layout_none if and only if this
+    * variable is \c gl_FragDepth and a layout qualifier is specified.
+    */
+   ir_depth_layout depth_layout;
+
+   /**
     * Was the location explicitly set in the shader?
     *
     * If the location is explicitly set in the shader, it \b cannot be changed
@@ -335,6 +379,22 @@ public:
    int location;
 
    /**
+    * Built-in state that backs this uniform
+    *
+    * Once set at variable creation, \c state_slots must remain invariant.
+    * This is because, ideally, this array would be shared by all clones of
+    * this variable in the IR tree.  In other words, we'd really like for it
+    * to be a fly-weight.
+    *
+    * If the variable is not a uniform, \c num_state_slots will be zero and
+    * \c state_slots will be \c NULL.
+    */
+   /*@{*/
+   unsigned num_state_slots;    /**< Number of state slots used */
+   ir_state_slot *state_slots;  /**< State descriptors. */
+   /*@}*/
+
+   /**
     * Emit a warning if this variable is accessed.
     */
    const char *warn_extension;
@@ -360,6 +420,8 @@ public:
 
    virtual ir_function_signature *clone(void *mem_ctx,
                                        struct hash_table *ht) const;
+   ir_function_signature *clone_prototype(void *mem_ctx,
+                                         struct hash_table *ht) const;
 
    virtual void accept(ir_visitor *v)
    {
@@ -603,7 +665,7 @@ public:
 
 class ir_assignment : public ir_instruction {
 public:
-   ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
+   ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition = NULL);
 
    /**
     * Construct an assignment with an explicit write mask
@@ -710,6 +772,8 @@ enum ir_expression_operation {
    ir_unop_i2b,      /**< int-to-boolean conversion */
    ir_unop_b2i,      /**< Boolean-to-int conversion */
    ir_unop_u2f,      /**< Unsigned-to-float conversion. */
+   ir_unop_i2u,      /**< Integer-to-unsigned conversion. */
+   ir_unop_u2i,      /**< Unsigned-to-integer conversion. */
    ir_unop_any,
 
    /**
@@ -729,6 +793,8 @@ enum ir_expression_operation {
    /*@{*/
    ir_unop_sin,
    ir_unop_cos,
+   ir_unop_sin_reduced,    /**< Reduced range sin. [-pi, pi] */
+   ir_unop_cos_reduced,    /**< Reduced range cos. [-pi, pi] */
    /*@}*/
 
    /**
@@ -810,6 +876,8 @@ enum ir_expression_operation {
     */
    ir_last_binop = ir_binop_pow,
 
+   ir_quadop_vector,
+
    /**
     * A sentinel marking the last of all operations.
     */
@@ -818,8 +886,24 @@ enum ir_expression_operation {
 
 class ir_expression : public ir_rvalue {
 public:
+   /**
+    * Constructor for unary operation expressions
+    */
+   ir_expression(int op, const struct glsl_type *type, ir_rvalue *);
+   ir_expression(int op, ir_rvalue *);
+
+   /**
+    * Constructor for binary operation expressions
+    */
    ir_expression(int op, const struct glsl_type *type,
                 ir_rvalue *, ir_rvalue *);
+   ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1);
+
+   /**
+    * Constructor for quad operator expressions
+    */
+   ir_expression(int op, const struct glsl_type *type,
+                ir_rvalue *, ir_rvalue *, ir_rvalue *, ir_rvalue *);
 
    virtual ir_expression *as_expression()
    {
@@ -846,7 +930,8 @@ public:
     */
    unsigned int get_num_operands() const
    {
-      return get_num_operands(operation);
+      return (this->operation == ir_quadop_vector)
+        ? this->type->vector_elements : get_num_operands(operation);
    }
 
    /**
@@ -873,7 +958,7 @@ public:
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
    ir_expression_operation operation;
-   ir_rvalue *operands[2];
+   ir_rvalue *operands[4];
 };
 
 
@@ -889,6 +974,7 @@ public:
       assert(callee->return_type != NULL);
       type = callee->return_type;
       actual_parameters->move_nodes_to(& this->actual_parameters);
+      this->use_builtin = callee->is_builtin;
    }
 
    virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
@@ -910,7 +996,7 @@ public:
    /**
     * Get a generic ir_call object when an error occurs
     *
-    * Any allocation will be performed with 'ctx' as talloc owner.
+    * Any allocation will be performed with 'ctx' as ralloc owner.
     */
    static ir_call *get_error_instruction(void *ctx);
 
@@ -952,6 +1038,9 @@ public:
    /* List of ir_rvalue of paramaters passed in this call. */
    exec_list actual_parameters;
 
+   /** Should this call only bind to a built-in function? */
+   bool use_builtin;
+
 private:
    ir_call()
       : callee(NULL)
@@ -1088,6 +1177,11 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual ir_discard *as_discard()
+   {
+      return this;
+   }
+
    ir_rvalue *condition;
 };
 /*@}*/
@@ -1101,7 +1195,8 @@ enum ir_texture_opcode {
    ir_txb,             /**< Texture look-up with LOD bias */
    ir_txl,             /**< Texture look-up with explicit LOD */
    ir_txd,             /**< Texture look-up with partial derivatvies */
-   ir_txf              /**< Texel fetch with explicit LOD */
+   ir_txf,             /**< Texel fetch with explicit LOD */
+   ir_txs              /**< Texture size */
 };
 
 
@@ -1112,21 +1207,22 @@ enum ir_texture_opcode {
  * selected from \c ir_texture_opcodes.  In the printed IR, these will
  * appear as:
  *
- *                              Texel offset
- *                              |       Projection divisor
- *                              |       |   Shadow comparitor
- *                              |       |   |
- *                              v       v   v
- * (tex (sampler) (coordinate) (0 0 0) (1) ( ))
- * (txb (sampler) (coordinate) (0 0 0) (1) ( ) (bias))
- * (txl (sampler) (coordinate) (0 0 0) (1) ( ) (lod))
- * (txd (sampler) (coordinate) (0 0 0) (1) ( ) (dPdx dPdy))
- * (txf (sampler) (coordinate) (0 0 0)         (lod))
+ *                                    Texel offset (0 or an expression)
+ *                                    | Projection divisor
+ *                                    | |  Shadow comparitor
+ *                                    | |  |
+ *                                    v v  v
+ * (tex <type> <sampler> <coordinate> 0 1 ( ))
+ * (txb <type> <sampler> <coordinate> 0 1 ( ) <bias>)
+ * (txl <type> <sampler> <coordinate> 0 1 ( ) <lod>)
+ * (txd <type> <sampler> <coordinate> 0 1 ( ) (dPdx dPdy))
+ * (txf <type> <sampler> <coordinate> 0       <lod>)
+ * (txs <type> <sampler> <lod>)
  */
 class ir_texture : public ir_rvalue {
 public:
    ir_texture(enum ir_texture_opcode op)
-      : op(op), projector(NULL), shadow_comparitor(NULL)
+      : op(op), projector(NULL), shadow_comparitor(NULL), offset(NULL)
    {
       this->ir_type = ir_type_texture;
    }
@@ -1147,8 +1243,8 @@ public:
     */
    const char *opcode_string();
 
-   /** Set the sampler and infer the type. */
-   void set_sampler(ir_dereference *sampler);
+   /** Set the sampler and type. */
+   void set_sampler(ir_dereference *sampler, const glsl_type *type);
 
    /**
     * Do a reverse-lookup to translate a string into an ir_texture_opcode.
@@ -1180,8 +1276,8 @@ public:
     */
    ir_rvalue *shadow_comparitor;
 
-   /** Explicit texel offsets. */
-   signed char offsets[3];
+   /** Texel offset. */
+   ir_rvalue *offset;
 
    union {
       ir_rvalue *lod;          /**< Floating point LOD */
@@ -1244,7 +1340,7 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   bool is_lvalue()
+   bool is_lvalue() const
    {
       return val->is_lvalue() && !mask.has_duplicates;
    }
@@ -1252,7 +1348,7 @@ public:
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
-   virtual ir_variable *variable_referenced();
+   virtual ir_variable *variable_referenced() const;
 
    ir_rvalue *val;
    ir_swizzle_mask mask;
@@ -1276,12 +1372,12 @@ public:
       return this;
    }
 
-   bool is_lvalue();
+   bool is_lvalue() const;
 
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
-   virtual ir_variable *variable_referenced() = 0;
+   virtual ir_variable *variable_referenced() const = 0;
 };
 
 
@@ -1302,7 +1398,7 @@ public:
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
-   virtual ir_variable *variable_referenced()
+   virtual ir_variable *variable_referenced() const
    {
       return this->var;
    }
@@ -1351,7 +1447,7 @@ public:
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
-   virtual ir_variable *variable_referenced()
+   virtual ir_variable *variable_referenced() const
    {
       return this->array->variable_referenced();
    }
@@ -1385,7 +1481,7 @@ public:
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
-   virtual ir_variable *variable_referenced()
+   virtual ir_variable *variable_referenced() const
    {
       return this->record->variable_referenced();
    }
@@ -1480,12 +1576,14 @@ public:
    /**
     * Determine whether a constant has the same value as another constant
     *
-    * \sa ir_constant::is_zero, ir_constant::is_one
+    * \sa ir_constant::is_zero, ir_constant::is_one,
+    * ir_constant::is_negative_one
     */
    bool has_value(const ir_constant *) const;
 
    virtual bool is_zero() const;
    virtual bool is_one() const;
+   virtual bool is_negative_one() const;
 
    /**
     * Value of the constant.
@@ -1522,6 +1620,32 @@ visit_exec_list(exec_list *list, ir_visitor *visitor);
  */
 void validate_ir_tree(exec_list *instructions);
 
+struct _mesa_glsl_parse_state;
+struct gl_shader_program;
+
+/**
+ * Detect whether an unlinked shader contains static recursion
+ *
+ * If the list of instructions is determined to contain static recursion,
+ * \c _mesa_glsl_error will be called to emit error messages for each function
+ * that is in the recursion cycle.
+ */
+void
+detect_recursion_unlinked(struct _mesa_glsl_parse_state *state,
+                         exec_list *instructions);
+
+/**
+ * Detect whether a linked shader contains static recursion
+ *
+ * If the list of instructions is determined to contain static recursion,
+ * \c link_error_printf will be called to emit error messages for each function
+ * that is in the recursion cycle.  In addition,
+ * \c gl_shader_program::LinkStatus will be set to false.
+ */
+void
+detect_recursion_linked(struct gl_shader_program *prog,
+                       exec_list *instructions);
+
 /**
  * Make a clone of each IR instruction in a list
  *
@@ -1536,8 +1660,7 @@ _mesa_glsl_initialize_variables(exec_list *instructions,
                                struct _mesa_glsl_parse_state *state);
 
 extern void
-_mesa_glsl_initialize_functions(exec_list *instructions,
-                               struct _mesa_glsl_parse_state *state);
+_mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state);
 
 extern void
 _mesa_glsl_release_functions(void);
@@ -1555,6 +1678,11 @@ extern bool
 ir_has_call(ir_instruction *ir);
 
 extern void
-do_set_program_inouts(exec_list *instructions, struct gl_program *prog);
+do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
+                      bool is_fragment_shader);
+
+extern char *
+prototype_string(const glsl_type *return_type, const char *name,
+                exec_list *parameters);
 
 #endif /* IR_H */