Revert "glsl: move xfb BufferStride into gl_transform_feedback_info"
[mesa.git] / src / compiler / glsl / ast_type.cpp
index 4fb4ac0df61ad57a917a337e9cd585a3970319d4..f3f6b29369b070bad4c40d5145456aedebeef29e 100644 (file)
@@ -175,9 +175,10 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
    /* Geometry shaders can have several layout qualifiers
     * assigning different stream values.
     */
-   if (state->stage == MESA_SHADER_GEOMETRY)
+   if (state->stage == MESA_SHADER_GEOMETRY) {
       allowed_duplicates_mask.flags.i |=
          stream_layout_mask.flags.i;
+   }
 
    if (is_single_layout_merge && !state->has_enhanced_layouts() &&
        (this->flags.i & q.flags.i & ~allowed_duplicates_mask.flags.i) != 0) {
@@ -226,7 +227,8 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
          if (q.flags.q.stream) {
             this->flags.q.stream = 1;
             this->stream = q.stream;
-         } else if (!this->flags.q.stream && this->flags.q.out) {
+         } else if (!this->flags.q.stream && this->flags.q.out &&
+                    !this->flags.q.in) {
             /* Assign default global stream value */
             this->flags.q.stream = 1;
             this->stream = state->out_qualifier->stream;
@@ -239,7 +241,8 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
          if (q.flags.q.xfb_buffer) {
             this->flags.q.xfb_buffer = 1;
             this->xfb_buffer = q.xfb_buffer;
-         } else if (!this->flags.q.xfb_buffer && this->flags.q.out) {
+         } else if (!this->flags.q.xfb_buffer && this->flags.q.out &&
+                    !this->flags.q.in) {
             /* Assign global xfb_buffer value */
             this->flags.q.xfb_buffer = 1;
             this->xfb_buffer = state->out_qualifier->xfb_buffer;
@@ -411,6 +414,8 @@ ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc,
       valid_out_mask.flags.q.xfb_buffer = 1;
       valid_out_mask.flags.q.explicit_xfb_stride = 1;
       valid_out_mask.flags.q.xfb_stride = 1;
+   } else if (state->stage == MESA_SHADER_FRAGMENT) {
+      valid_out_mask.flags.q.blend_support = 1;
    } else {
       _mesa_glsl_error(loc, state, "out layout qualifiers only valid in "
                        "geometry, tessellation and vertex shaders");
@@ -597,8 +602,8 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
 bool
 ast_type_qualifier::validate_flags(YYLTYPE *loc,
                                    _mesa_glsl_parse_state *state,
-                                   const char *message,
-                                   const ast_type_qualifier &allowed_flags)
+                                   const ast_type_qualifier &allowed_flags,
+                                   const char *message, const char *name)
 {
    ast_type_qualifier bad;
    bad.flags.i = this->flags.i & ~allowed_flags.flags.i;
@@ -606,11 +611,11 @@ ast_type_qualifier::validate_flags(YYLTYPE *loc,
       return true;
 
    _mesa_glsl_error(loc, state,
-                    "%s:"
+                    "%s '%s':"
                     "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
                     "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
-                    "%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
-                    message,
+                    "%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+                    message, name,
                     bad.flags.q.invariant ? " invariant" : "",
                     bad.flags.q.precise ? " precise" : "",
                     bad.flags.q.constant ? " constant" : "",
@@ -630,6 +635,7 @@ ast_type_qualifier::validate_flags(YYLTYPE *loc,
                     bad.flags.q.origin_upper_left ? " origin_upper_left" : "",
                     bad.flags.q.pixel_center_integer ? " pixel_center_integer" : "",
                     bad.flags.q.explicit_align ? " align" : "",
+                    bad.flags.q.explicit_component ? " component" : "",
                     bad.flags.q.explicit_location ? " location" : "",
                     bad.flags.q.explicit_index ? " index" : "",
                     bad.flags.q.explicit_binding ? " binding" : "",
@@ -675,7 +681,8 @@ bool
 ast_layout_expression::process_qualifier_constant(struct _mesa_glsl_parse_state *state,
                                                   const char *qual_indentifier,
                                                   unsigned *value,
-                                                  bool can_be_zero)
+                                                  bool can_be_zero,
+                                                  bool must_match)
 {
    int min_value = 0;
    bool first_pass = true;
@@ -684,8 +691,8 @@ ast_layout_expression::process_qualifier_constant(struct _mesa_glsl_parse_state
    if (!can_be_zero)
       min_value = 1;
 
-   for (exec_node *node = layout_const_expressions.head;
-           !node->is_tail_sentinel(); node = node->next) {
+   for (exec_node *node = layout_const_expressions.get_head_raw();
+        !node->is_tail_sentinel(); node = node->next) {
 
       exec_list dummy_instructions;
       ast_node *const_expression = exec_node_data(ast_node, node, link);
@@ -708,12 +715,19 @@ ast_layout_expression::process_qualifier_constant(struct _mesa_glsl_parse_state
          return false;
       }
 
-      if (!first_pass && *value != const_int->value.u[0]) {
-         YYLTYPE loc = const_expression->get_location();
-         _mesa_glsl_error(&loc, state, "%s layout qualifier does not "
-                         "match previous declaration (%d vs %d)",
-                          qual_indentifier, *value, const_int->value.i[0]);
-         return false;
+      /* From section 4.4 "Layout Qualifiers" of the GLSL 4.50 spec:
+       * "When the same layout-qualifier-name occurs multiple times,
+       *  in a single declaration, the last occurrence overrides the
+       *  former occurrence(s)."
+       */
+      if (!first_pass) {
+         if ((must_match || !state->has_420pack()) && *value != const_int->value.u[0]) {
+            YYLTYPE loc = const_expression->get_location();
+            _mesa_glsl_error(&loc, state, "%s layout qualifier does not "
+                             "match previous declaration (%d vs %d)",
+                             qual_indentifier, *value, const_int->value.i[0]);
+            return false;
+         }
       } else {
          first_pass = false;
          *value = const_int->value.u[0];