glsl: process blend_support_* qualifiers
[mesa.git] / src / compiler / glsl / glsl_parser.yy
index 146589a5aa41dd7527aeb7ebd767d5f718994a9b..4043dae5e1ac708194e96de78be4334e37033a08 100644 (file)
@@ -1274,7 +1274,8 @@ layout_qualifier_id:
             }
          }
 
-         if ($$.flags.i && !state->has_geometry_shader()) {
+         if ($$.flags.i && !state->has_geometry_shader() &&
+             !state->has_tessellation_shader()) {
             _mesa_glsl_error(& @1, state, "#version 150 layout "
                              "qualifier `%s' used", $1);
          }
@@ -1372,7 +1373,7 @@ layout_qualifier_id:
 
       /* Layout qualifiers for tessellation evaluation shaders. */
       if (!$$.flags.i) {
-         struct {
+         static const struct {
             const char *s;
             GLenum e;
          } map[] = {
@@ -1395,7 +1396,7 @@ layout_qualifier_id:
          }
       }
       if (!$$.flags.i) {
-         struct {
+         static const struct {
             const char *s;
             GLenum e;
          } map[] = {
@@ -1445,6 +1446,51 @@ layout_qualifier_id:
          }
       }
 
+      if (!$$.flags.i) {
+         static const struct {
+            const char *s;
+            uint32_t mask;
+         } map[] = {
+                 { "blend_support_multiply",       BLEND_MULTIPLY },
+                 { "blend_support_screen",         BLEND_SCREEN },
+                 { "blend_support_overlay",        BLEND_OVERLAY },
+                 { "blend_support_darken",         BLEND_DARKEN },
+                 { "blend_support_lighten",        BLEND_LIGHTEN },
+                 { "blend_support_colordodge",     BLEND_COLORDODGE },
+                 { "blend_support_colorburn",      BLEND_COLORBURN },
+                 { "blend_support_hardlight",      BLEND_HARDLIGHT },
+                 { "blend_support_softlight",      BLEND_SOFTLIGHT },
+                 { "blend_support_difference",     BLEND_DIFFERENCE },
+                 { "blend_support_exclusion",      BLEND_EXCLUSION },
+                 { "blend_support_hsl_hue",        BLEND_HSL_HUE },
+                 { "blend_support_hsl_saturation", BLEND_HSL_SATURATION },
+                 { "blend_support_hsl_color",      BLEND_HSL_COLOR },
+                 { "blend_support_hsl_luminosity", BLEND_HSL_LUMINOSITY },
+                 { "blend_support_all_equations",  BLEND_ALL },
+         };
+         for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
+            if (match_layout_qualifier($1, map[i].s, state) == 0) {
+               $$.flags.q.blend_support = 1;
+               state->fs_blend_support |= map[i].mask;
+               break;
+            }
+         }
+
+         if ($$.flags.i &&
+             !state->KHR_blend_equation_advanced_enable &&
+             !state->is_version(0, 320)) {
+            _mesa_glsl_error(& @1, state,
+                             "advanced blending layout qualifiers require "
+                             "ESSL 3.20 or KHR_blend_equation_advanced");
+         }
+
+         if ($$.flags.i && state->stage != MESA_SHADER_FRAGMENT) {
+            _mesa_glsl_error(& @1, state,
+                             "advanced blending layout qualifiers only "
+                             "valid in fragment shaders");
+         }
+      }
+
       if (!$$.flags.i) {
          _mesa_glsl_error(& @1, state, "unrecognized layout identifier "
                           "`%s'", $1);
@@ -1773,8 +1819,10 @@ type_qualifier:
        * variables. As only outputs can be declared as invariant, an invariant
        * output from one shader stage will still match an input of a subsequent
        * stage without the input being declared as invariant."
+       *
+       * On the desktop side, this text first appears in GLSL 4.30.
        */
-      if (state->es_shader && state->language_version >= 300 && $$.flags.q.in)
+      if (state->is_version(430, 300) && $$.flags.q.in)
          _mesa_glsl_error(&@1, state, "invariant qualifiers cannot be used with shader inputs");
    }
    | interpolation_qualifier type_qualifier
@@ -1941,6 +1989,18 @@ storage_qualifier:
           $$.xfb_buffer = state->out_qualifier->xfb_buffer;
       }
    }
+   | INOUT_TOK
+   {
+      memset(& $$, 0, sizeof($$));
+      $$.flags.q.in = 1;
+      $$.flags.q.out = 1;
+
+      if (!state->has_framebuffer_fetch() ||
+          !state->is_version(130, 300) ||
+          state->stage != MESA_SHADER_FRAGMENT)
+         _mesa_glsl_error(&@1, state, "A single interface variable cannot be "
+                          "declared as both input and output");
+   }
    | UNIFORM
    {
       memset(& $$, 0, sizeof($$));