Adding new glsl interpolation qualifiers

This adds proper handling of the new
interpolation qualifiers "flat" and
"smooth" for glsl in OpenGL ES 3.0.
These aren't implemented yet, they are
simply parsed properly with this cl.

Change-Id: I32aa2ca0f9ddb4c2b1a1e9c5f285a41a1716f4cc
Reviewed-on: https://swiftshader-review.googlesource.com/2861
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/compiler/ParseHelper.cpp b/src/OpenGL/compiler/ParseHelper.cpp
index b8ca5cc..f1287cc 100644
--- a/src/OpenGL/compiler/ParseHelper.cpp
+++ b/src/OpenGL/compiler/ParseHelper.cpp
@@ -315,6 +315,9 @@
     case EvqConstReadOnly:  message = "can't modify a const";        break;
     case EvqAttribute:      message = "can't modify an attribute";   break;
     case EvqUniform:        message = "can't modify a uniform";      break;
+    case EvqSmoothIn:
+    case EvqFlatIn:
+    case EvqCentroidIn:
     case EvqVaryingIn:      message = "can't modify a varying";      break;
     case EvqInput:          message = "can't modify an input";       break;
     case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
@@ -609,12 +612,27 @@
 
 bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
 {
-    if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
-        pType.type == EbtStruct) {
-        error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
+	switch(pType.qualifier)
+	{
+	case EvqVaryingOut:
+	case EvqSmooth:
+	case EvqFlat:
+	case EvqCentroidOut:
+	case EvqVaryingIn:
+	case EvqSmoothIn:
+	case EvqFlatIn:
+	case EvqCentroidIn:
+	case EvqAttribute:
+		if(pType.type == EbtStruct)
+		{
+			error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
 
-        return true;
-    }
+			return true;
+		}
+		break;
+	default:
+		break;
+	}
 
     if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
         return true;
@@ -1381,6 +1399,52 @@
     return joinedQualifier;
 }
 
+
+TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
+	const TSourceLoc &storageLoc, TQualifier storageQualifier)
+{
+	TQualifier mergedQualifier = EvqSmoothIn;
+
+	if(storageQualifier == EvqVaryingIn) {
+		if(interpolationQualifier == EvqSmooth)
+			mergedQualifier = EvqSmoothIn;
+		else if(interpolationQualifier == EvqFlat)
+			mergedQualifier = EvqFlatIn;
+		else UNREACHABLE();
+	}
+	else if(storageQualifier == EvqCentroidIn) {
+		if(interpolationQualifier == EvqSmooth)
+			mergedQualifier = EvqCentroidIn;
+		else if(interpolationQualifier == EvqFlat)
+			mergedQualifier = EvqFlatIn;
+		else UNREACHABLE();
+	}
+	else if(storageQualifier == EvqVaryingOut) {
+		if(interpolationQualifier == EvqSmooth)
+			mergedQualifier = EvqSmoothOut;
+		else if(interpolationQualifier == EvqFlat)
+			mergedQualifier = EvqFlatOut;
+		else UNREACHABLE();
+	}
+	else if(storageQualifier == EvqCentroidOut) {
+		if(interpolationQualifier == EvqSmooth)
+			mergedQualifier = EvqCentroidOut;
+		else if(interpolationQualifier == EvqFlat)
+			mergedQualifier = EvqFlatOut;
+		else UNREACHABLE();
+	}
+	else {
+		error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getQualifierString(interpolationQualifier));
+		recover();
+
+		mergedQualifier = storageQualifier;
+	}
+
+	TPublicType type;
+	type.setBasic(EbtVoid, mergedQualifier, storageLoc);
+	return type;
+}
+
 bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
 {
     ++structNestingLevel;