Revert "i965/fs: Change fs_visitor::emit_lrp to use MAC for gen<6"
[mesa.git] / src / glsl / ast_to_hir.cpp
index 35d58e908307ef76b4ef7489b78e0712eb3df7d8..0128b3f4e82f8e872bb8e872955c49429d6416ae 100644 (file)
@@ -123,6 +123,11 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
       instructions->push_head(var);
    }
 
+   /* Figure out if gl_FragCoord is actually used in fragment shader */
+   ir_variable *const var = state->symbols->get_variable("gl_FragCoord");
+   if (var != NULL)
+      state->fs_uses_gl_fragcoord = var->data.used;
+
    /* From section 7.1 (Built-In Language Variables) of the GLSL 4.10 spec:
     *
     *     If multiple shaders using members of a built-in block belonging to
@@ -794,11 +799,10 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
                           "assignment to %s",
                           non_lvalue_description);
          error_emitted = true;
-      } else if (lhs->variable_referenced() != NULL
-                 && lhs->variable_referenced()->data.read_only) {
+      } else if (lhs_var != NULL && lhs_var->data.read_only) {
          _mesa_glsl_error(&lhs_loc, state,
                           "assignment to read-only variable '%s'",
-                          lhs->variable_referenced()->name);
+                          lhs_var->name);
          error_emitted = true;
       } else if (lhs->type->is_array() &&
                  !state->check_version(120, 300, &lhs_loc,
@@ -2341,6 +2345,34 @@ apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual,
    }
 }
 
+static inline const char*
+get_layout_qualifier_string(bool origin_upper_left, bool pixel_center_integer)
+{
+   if (origin_upper_left && pixel_center_integer)
+      return "origin_upper_left, pixel_center_integer";
+   else if (origin_upper_left)
+      return "origin_upper_left";
+   else if (pixel_center_integer)
+      return "pixel_center_integer";
+   else
+      return " ";
+}
+
+static inline bool
+is_conflicting_fragcoord_redeclaration(struct _mesa_glsl_parse_state *state,
+                                       const struct ast_type_qualifier *qual)
+{
+   /* If gl_FragCoord was previously declared, and the qualifiers were
+    * different in any way, return true.
+    */
+   if (state->fs_redeclares_gl_fragcoord) {
+      return (state->fs_pixel_center_integer != qual->flags.q.pixel_center_integer
+         || state->fs_origin_upper_left != qual->flags.q.origin_upper_left);
+   }
+
+   return false;
+}
+
 static void
 apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
                                  ir_variable *var,
@@ -2505,6 +2537,53 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
                       qual_string);
    }
 
+   if (var->name != NULL && strcmp(var->name, "gl_FragCoord") == 0) {
+
+      /* Section 4.3.8.1, page 39 of GLSL 1.50 spec says:
+       *
+       *    "Within any shader, the first redeclarations of gl_FragCoord
+       *     must appear before any use of gl_FragCoord."
+       *
+       * Generate a compiler error if above condition is not met by the
+       * fragment shader.
+       */
+      ir_variable *earlier = state->symbols->get_variable("gl_FragCoord");
+      if (earlier != NULL &&
+          earlier->data.used &&
+          !state->fs_redeclares_gl_fragcoord) {
+         _mesa_glsl_error(loc, state,
+                          "gl_FragCoord used before its first redeclaration "
+                          "in fragment shader");
+      }
+
+      /* Make sure all gl_FragCoord redeclarations specify the same layout
+       * qualifiers.
+       */
+      if (is_conflicting_fragcoord_redeclaration(state, qual)) {
+         const char *const qual_string =
+            get_layout_qualifier_string(qual->flags.q.origin_upper_left,
+                                        qual->flags.q.pixel_center_integer);
+
+         const char *const state_string =
+            get_layout_qualifier_string(state->fs_origin_upper_left,
+                                        state->fs_pixel_center_integer);
+
+         _mesa_glsl_error(loc, state,
+                          "gl_FragCoord redeclared with different layout "
+                          "qualifiers (%s) and (%s) ",
+                          state_string,
+                          qual_string);
+      }
+      state->fs_origin_upper_left = qual->flags.q.origin_upper_left;
+      state->fs_pixel_center_integer = qual->flags.q.pixel_center_integer;
+      state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers =
+         !qual->flags.q.origin_upper_left && !qual->flags.q.pixel_center_integer;
+      state->fs_redeclares_gl_fragcoord =
+         state->fs_origin_upper_left ||
+         state->fs_pixel_center_integer ||
+         state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers;
+   }
+
    if (qual->flags.q.explicit_location) {
       validate_explicit_location(qual, var, state, loc);
    } else if (qual->flags.q.explicit_index) {
@@ -3065,16 +3144,10 @@ ast_declarator_list::hir(exec_list *instructions,
             _mesa_glsl_error(& loc, state,
                              "undeclared variable `%s' cannot be marked "
                              "invariant", decl->identifier);
-         } else if ((state->stage == MESA_SHADER_VERTEX)
-                    && (earlier->data.mode != ir_var_shader_out)) {
-            _mesa_glsl_error(& loc, state,
-                             "`%s' cannot be marked invariant, vertex shader "
-                             "outputs only", decl->identifier);
-         } else if ((state->stage == MESA_SHADER_FRAGMENT)
-                    && (earlier->data.mode != ir_var_shader_in)) {
-            _mesa_glsl_error(& loc, state,
-                             "`%s' cannot be marked invariant, fragment shader "
-                             "inputs only", decl->identifier);
+         } else if (!is_varying_var(earlier, state->stage)) {
+            _mesa_glsl_error(&loc, state,
+                             "`%s' cannot be marked invariant; interfaces between "
+                             "shader stages only.", decl->identifier);
          } else if (earlier->data.used) {
             _mesa_glsl_error(& loc, state,
                             "variable `%s' may not be redeclared "
@@ -3250,19 +3323,10 @@ ast_declarator_list::hir(exec_list *instructions,
                                       & loc, false);
 
       if (this->type->qualifier.flags.q.invariant) {
-         if ((state->stage == MESA_SHADER_VERTEX) &&
-             var->data.mode != ir_var_shader_out) {
-            _mesa_glsl_error(& loc, state,
-                             "`%s' cannot be marked invariant, vertex shader "
-                             "outputs only", var->name);
-         } else if ((state->stage == MESA_SHADER_FRAGMENT) &&
-                    var->data.mode != ir_var_shader_in) {
-            /* FINISHME: Note that this doesn't work for invariant on
-             * a function signature inval
-             */
-            _mesa_glsl_error(& loc, state,
-                             "`%s' cannot be marked invariant, fragment shader "
-                             "inputs only", var->name);
+         if (!is_varying_var(var, state->stage)) {
+            _mesa_glsl_error(&loc, state,
+                             "`%s' cannot be marked invariant; interfaces between "
+                             "shader stages only", var->name);
          }
       }