diff --git a/Test/310.frag b/Test/310.frag
index 3de390a908085c010b60285127c28d137f1c283f..116a0a733c4b061a5a6b7e6205bd96d6957fea33 100644
--- a/Test/310.frag
+++ b/Test/310.frag
@@ -397,3 +397,33 @@ void interp()
     res4 = interpolateAtSample(outp, 0);       // ERROR, not interpolant
 }
 
+layout(blend_support_softlight) out;           // ERROR, need extension
+
+#ifdef GL_KHR_blend_equation_advanced
+#extension GL_KHR_blend_equation_advanced : enable
+#endif
+
+layout(blend_support_multiply) out;
+layout(blend_support_screen) out;
+layout(blend_support_overlay) out;
+layout(blend_support_darken, blend_support_lighten) out;
+layout(blend_support_colordodge) layout(blend_support_colorburn) out;
+layout(blend_support_hardlight) out;
+layout(blend_support_softlight) out;
+layout(blend_support_difference) out;
+layout(blend_support_exclusion) out;
+layout(blend_support_hsl_hue) out;
+layout(blend_support_hsl_saturation) out;
+layout(blend_support_hsl_color) out;
+layout(blend_support_hsl_luminosity) out;
+layout(blend_support_all_equations) out;
+
+layout(blend_support_hsl_luminosity) out;              // okay to repeat
+
+layout(blend_support_hsl_luminosity) in;                       // ERROR, only on "out"
+layout(blend_support_hsl_luminosity) out vec4;                 // ERROR, only on standalone
+layout(blend_support_hsl_luminosity) out vec4 badout;          // ERROR, only on standalone
+layout(blend_support_hsl_luminosity) struct badS {int i;};     // ERROR, only on standalone
+layout(blend_support_hsl_luminosity) void blendFoo() { }       // ERROR, only on standalone
+void blendFoo(layout(blend_support_hsl_luminosity) vec3 v) { } // ERROR, only on standalone
+layout(blend_support_flizbit) out;                             // ERROR, no flizbit
diff --git a/Test/baseResults/310.frag.out b/Test/baseResults/310.frag.out
index 40e0e2d48c176d10903e55e145118cda82a06141..910cd9c5558b8d0e4f4b0131872d1ec1d051791f 100644
--- a/Test/baseResults/310.frag.out
+++ b/Test/baseResults/310.frag.out
@@ -121,12 +121,21 @@ ERROR: 0:391: 'interpolateAtOffset' : first argument must be an interpolant, or
 ERROR: 0:392: 'interpolateAtOffset' : first argument must be an interpolant, or interpolant-array element 
 ERROR: 0:396: 'interpolateAtCentroid' : first argument must be an interpolant, or interpolant-array element 
 ERROR: 0:397: 'interpolateAtSample' : first argument must be an interpolant, or interpolant-array element 
-ERROR: 113 compilation errors.  No code generated.
+ERROR: 0:400: 'blend equation' : required extension not requested: GL_KHR_blend_equation_advanced
+ERROR: 0:423: 'blend equation' : can only apply to 'out' 
+ERROR: 0:424: 'blend equation' : can only apply to a standalone qualifier 
+ERROR: 0:425: 'blend equation' : can only apply to a standalone qualifier 
+ERROR: 0:426: 'blend equation' : can only apply to a standalone qualifier 
+ERROR: 0:427: 'blend equation' : can only apply to a standalone qualifier 
+ERROR: 0:428: 'blend equation' : can only apply to a standalone qualifier 
+ERROR: 0:429: 'blend_support' : unknown blend equation 
+ERROR: 121 compilation errors.  No code generated.
 
 
 Shader version: 310
 Requested GL_EXT_shader_io_blocks
 Requested GL_EXT_texture_cube_map_array
+Requested GL_KHR_blend_equation_advanced
 Requested GL_OES_geometry_shader
 Requested GL_OES_gpu_shader5
 Requested GL_OES_sample_variables
@@ -137,6 +146,7 @@ gl_FragCoord pixel center is integer
 gl_FragCoord origin is upper left
 using early_fragment_tests
 using depth_any
+using blend_support_multiply blend_support_screen blend_support_overlay blend_support_darken blend_support_lighten blend_support_colordodge blend_support_colorburn blend_support_hardlight blend_support_softlight blend_support_difference blend_support_exclusion blend_support_hsl_hue blend_support_hsl_saturation blend_support_hsl_color blend_support_hsl_luminosity blend_support_all_equations
 ERROR: node is still EOpNull!
 0:21  Function Definition: main( (global void)
 0:21    Function Parameters: 
@@ -897,6 +907,11 @@ ERROR: node is still EOpNull!
 0:397          'outp' (out mediump 4-component vector of float)
 0:397          Constant:
 0:397            0 (const int)
+0:427  Function Definition: blendFoo( (temp void)
+0:427    Function Parameters: 
+0:428  Function Definition: blendFoo(vf3; (global void)
+0:428    Function Parameters: 
+0:428      'v' (in mediump 3-component vector of float)
 0:?   Linker Objects
 0:?     'gl_FragCoord' (smooth in mediump 4-component vector of float)
 0:?     'v3' (layout(location=2 ) smooth in mediump 3-component vector of float)
@@ -990,6 +1005,7 @@ ERROR: node is still EOpNull!
 0:?     'colorSampleBad' (sample out mediump 4-component vector of float)
 0:?     'colorfsi' (flat sample in mediump 4-component vector of float)
 0:?     'sampInArray' (smooth sample in 4-element array of mediump 3-component vector of float)
+0:?     'badout' (out mediump 4-component vector of float)
 
 
 Linked fragment stage:
@@ -999,6 +1015,7 @@ ERROR: Linking fragment stage: when more than one fragment shader output, all mu
 Shader version: 310
 Requested GL_EXT_shader_io_blocks
 Requested GL_EXT_texture_cube_map_array
+Requested GL_KHR_blend_equation_advanced
 Requested GL_OES_geometry_shader
 Requested GL_OES_gpu_shader5
 Requested GL_OES_sample_variables
@@ -1009,6 +1026,7 @@ gl_FragCoord pixel center is integer
 gl_FragCoord origin is upper left
 using early_fragment_tests
 using depth_any
+using blend_support_multiply blend_support_screen blend_support_overlay blend_support_darken blend_support_lighten blend_support_colordodge blend_support_colorburn blend_support_hardlight blend_support_softlight blend_support_difference blend_support_exclusion blend_support_hsl_hue blend_support_hsl_saturation blend_support_hsl_color blend_support_hsl_luminosity blend_support_all_equations
 ERROR: node is still EOpNull!
 0:21  Function Definition: main( (global void)
 0:21    Function Parameters: 
@@ -1769,6 +1787,11 @@ ERROR: node is still EOpNull!
 0:397          'outp' (out mediump 4-component vector of float)
 0:397          Constant:
 0:397            0 (const int)
+0:427  Function Definition: blendFoo( (temp void)
+0:427    Function Parameters: 
+0:428  Function Definition: blendFoo(vf3; (global void)
+0:428    Function Parameters: 
+0:428      'v' (in mediump 3-component vector of float)
 0:?   Linker Objects
 0:?     'gl_FragCoord' (smooth in mediump 4-component vector of float)
 0:?     'v3' (layout(location=2 ) smooth in mediump 3-component vector of float)
@@ -1862,4 +1885,5 @@ ERROR: node is still EOpNull!
 0:?     'colorSampleBad' (sample out mediump 4-component vector of float)
 0:?     'colorfsi' (flat sample in mediump 4-component vector of float)
 0:?     'sampInArray' (smooth sample in 4-element array of mediump 3-component vector of float)
+0:?     'badout' (out mediump 4-component vector of float)
 
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index 8900b5b433c3104752d2c45cde6ebfea53df6089..c765d44375eb057de0a1ae69349e0994b3f4bdc7 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -294,6 +294,30 @@ enum TLayoutDepth {
     EldCount
 };
 
+enum TBlendEquationShift {
+    // No 'EBlendNone':
+    // These are used as bit-shift amounts.  A mask of such shifts will have type 'int',
+    // and in that space, 0 means no bits set, or none.  In this enum, 0 means (1 << 0), a bit is set.
+    EBlendMultiply,
+    EBlendScreen,
+    EBlendOverlay,
+    EBlendDarken,
+    EBlendLighten,
+    EBlendColordodge,
+    EBlendColorburn,
+    EBlendHardlight,
+    EBlendSoftlight,
+    EBlendDifference,
+    EBlendExclusion,
+    EBlendHslHue,
+    EBlendHslSaturation,
+    EBlendHslColor,
+    EBlendHslLuminosity,
+    EBlendAllEquations,
+
+    EBlendCount
+};
+
 class TQualifier {
 public:
     void clear()
@@ -669,6 +693,28 @@ public:
         default:           return "none";
         }
     }
+    static const char* getBlendEquationString(TBlendEquationShift e)
+    {
+        switch (e) {
+        case EBlendMultiply:      return "blend_support_multiply";
+        case EBlendScreen:        return "blend_support_screen";
+        case EBlendOverlay:       return "blend_support_overlay";
+        case EBlendDarken:        return "blend_support_darken";
+        case EBlendLighten:       return "blend_support_lighten";
+        case EBlendColordodge:    return "blend_support_colordodge";
+        case EBlendColorburn:     return "blend_support_colorburn";
+        case EBlendHardlight:     return "blend_support_hardlight";
+        case EBlendSoftlight:     return "blend_support_softlight";
+        case EBlendDifference:    return "blend_support_difference";
+        case EBlendExclusion:     return "blend_support_exclusion";
+        case EBlendHslHue:        return "blend_support_hsl_hue";
+        case EBlendHslSaturation: return "blend_support_hsl_saturation";
+        case EBlendHslColor:      return "blend_support_hsl_color";
+        case EBlendHslLuminosity: return "blend_support_hsl_luminosity";
+        case EBlendAllEquations:  return "blend_support_all_equations";
+        default:                  return "unknown";
+        }
+    }
     static const char* getGeometryString(TLayoutGeometry geometry)
     {
         switch (geometry) {
@@ -728,6 +774,7 @@ struct TShaderQualifiers {
     int localSize[3];         // compute shader
     bool earlyFragmentTests;  // fragment input
     TLayoutDepth layoutDepth;
+    bool blendEquation;       // true if any blend equation was specified
 
     void init()
     {
@@ -744,6 +791,7 @@ struct TShaderQualifiers {
         localSize[2] = 1;
         earlyFragmentTests = false;
         layoutDepth = EldNone;
+        blendEquation = false;
     }
 
     // Merge in characteristics from the 'src' qualifier.  They can override when
@@ -774,6 +822,8 @@ struct TShaderQualifiers {
             earlyFragmentTests = true;
         if (src.layoutDepth)
             layoutDepth = src.layoutDepth;
+        if (src.blendEquation)
+            blendEquation = src.blendEquation;
     }
 };
 
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index f983313f1317ac4e255516b4bb331477cedffc60..b52e63e8f79a5ed5122573648d097a8a1542425d 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -2379,6 +2379,9 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
     if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
         return;
 
+    if (publicType.shaderQualifiers.blendEquation)
+        error(loc, "can only be applied to a standalone 'out'", "blend equation", "");
+
     // now, knowing it is a shader in/out, do all the in/out semantic checks
 
     if (publicType.basicType == EbtBool) {
@@ -3694,6 +3697,21 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
                 return;
             }
         }
+        if (id.compare(0, 13, "blend_support") == 0) {
+            bool found = false;
+            for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
+                if (id == TQualifier::getBlendEquationString(be)) {
+                    requireExtensions(loc, 1, &E_GL_KHR_blend_equation_advanced, "blend equation");
+                    intermediate.addBlendEquation(be);
+                    publicType.shaderQualifiers.blendEquation = true;
+                    found = true;
+                    break;
+                }
+            }
+            if (! found)
+                error(loc, "unknown blend equation", "blend_support", "");
+            return;
+        }
     }
     error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
 }
@@ -4232,6 +4250,9 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua
         if (shaderQualifiers.localSize[i] > 1)
             error(loc, message, "local_size", "");
     }
+    if (shaderQualifiers.blendEquation)
+        error(loc, message, "blend equation", "");
+    // TBD: correctness: are any of these missing?  pixelCenterInteger, originUpperLeft, spacing, order, pointmode, earlyfragment, depth
 }
 
 // Correct and/or advance an object's offset layout qualifier.
@@ -5480,6 +5501,10 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
         else
             error(loc, "can only apply to 'in'", "early_fragment_tests", "");
     }
+    if (publicType.shaderQualifiers.blendEquation) {
+        if (publicType.qualifier.storage != EvqVaryingOut)
+            error(loc, "can only apply to 'out'", "blend equation", "");
+    }
 
     const TQualifier& qualifier = publicType.qualifier;
 
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index a269ea3d2d0ea007b1df243a5d0f2270e1ec4219..28f81061049d041d3ab26da0d4dc660d6cb4040c 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -179,8 +179,8 @@ void TParseContext::initializeExtensionBehavior()
     extensionBehavior[E_GL_GOOGLE_include_directive]                 = EBhDisable;
 
     // AEP
-    extensionBehavior[E_GL_ANDROID_extension_pack_es31a]             = EBhDisablePartial;
-    extensionBehavior[E_GL_KHR_blend_equation_advanced]              = EBhDisablePartial;
+    extensionBehavior[E_GL_ANDROID_extension_pack_es31a]             = EBhDisable;
+    extensionBehavior[E_GL_KHR_blend_equation_advanced]              = EBhDisable;
     extensionBehavior[E_GL_OES_sample_variables]                     = EBhDisable;
     extensionBehavior[E_GL_OES_shader_image_atomic]                  = EBhDisable;
     extensionBehavior[E_GL_OES_shader_multisample_interpolation]     = EBhDisable;
diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp
index 7edae3884397316c946b6bbae3cc20de16c6d2e4..015f91e67002e1531cff86b50e2ac186e30e3162 100644
--- a/glslang/MachineIndependent/intermOut.cpp
+++ b/glslang/MachineIndependent/intermOut.cpp
@@ -740,6 +740,15 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
             infoSink.debug << "using early_fragment_tests\n";
         if (depthLayout != EldNone)
             infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n";
+        if (blendEquations != 0) {
+            infoSink.debug << "using";
+            // blendEquations is a mask, decode it
+            for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
+                if (blendEquations & (1 << be))
+                    infoSink.debug << " " << TQualifier::getBlendEquationString(be);
+            }
+            infoSink.debug << "\n";
+        }
         break;
 
     case EShLangCompute:
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index 643c8883d441803b9d1ccbe2de2b3a8d8b451f34..19edae46f2692714ba98c9a4384dd1784892f464 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -88,6 +88,8 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
     else if (depthLayout != unit.depthLayout)
         error(infoSink, "Contradictory depth layouts");
 
+    blendEquations |= unit.blendEquations;
+
     if (inputPrimitive == ElgNone)
         inputPrimitive = unit.inputPrimitive;
     else if (inputPrimitive != unit.inputPrimitive)
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 627f503b361610adc471d88b5ae8eeda9add58ff..dedf1e68a34d255292d65f6aafa4b06db22ce828 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -127,7 +127,7 @@ public:
     explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), 
         numMains(0), numErrors(0), recursive(false),
         invocations(0), vertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false),
-        vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), xfbMode(false)
+        vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), blendEquations(0), xfbMode(false)
     {
         localSize[0] = 1;
         localSize[1] = 1;
@@ -277,6 +277,9 @@ public:
     }
     TLayoutDepth getDepth() const { return depthLayout; }
 
+    void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
+    unsigned int getBlendEquations() const { return blendEquations; }
+
     void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
     void merge(TInfoSink&, TIntermediate&);
     void finalCheck(TInfoSink&);
@@ -332,6 +335,7 @@ protected:
     int localSize[3];
     bool earlyFragmentTests;
     TLayoutDepth depthLayout;
+    int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
     bool xfbMode;
 
     typedef std::list<TCall> TGraph;