Allow dynamic loop cases to fail on GLSL ES 100.

- Add "require full_glsl_es_100_support" to annotate GLSL ES 100 test
  that use features that are not within the required subset required by
  the GLES 2. Cases with this annotation will report NotSupported if
  compile fails, or QualityWarning if linking fails.
- Mark affected tests with "require full_glsl_es_100_support"

Bug: 19678840
Change-Id: If13a79d0221c92da80b1c1fa18f98335f91abfd4
diff --git a/data/gles2/shaders/functions.test b/data/gles2/shaders/functions.test
index 62f8879..83cff96 100644
--- a/data/gles2/shaders/functions.test
+++ b/data/gles2/shaders/functions.test
@@ -2355,6 +2355,8 @@
 	end
 
 	case return_after_loop_sequence
+		require full_glsl_es_100_support
+
 		values
 		{
 			input float in0		= [ -0.5 | 1.5 ];
diff --git a/data/gles2/shaders/scoping.test b/data/gles2/shaders/scoping.test
index 5408704..23e274b 100644
--- a/data/gles2/shaders/scoping.test
+++ b/data/gles2/shaders/scoping.test
@@ -106,6 +106,7 @@
 
 	case while_condition_variable_hides_local_variable
 		version 100 es
+		require full_glsl_es_100_support
 		values
 		{
 			input int in0 = [ 1 | 2 | 3 ];
@@ -160,6 +161,7 @@
 
 	case while_condition_variable_hides_global_variable
 		version 100 es
+		require full_glsl_es_100_support
 		values
 		{
 			input int in0 = [ 1 | 2 | 3 ];
diff --git a/modules/glshared/glsShaderLibrary.cpp b/modules/glshared/glsShaderLibrary.cpp
index a263a44..a97823c 100644
--- a/modules/glshared/glsShaderLibrary.cpp
+++ b/modules/glshared/glsShaderLibrary.cpp
@@ -997,6 +997,12 @@
 
 		valueBlock = ShaderCase::CaseRequirement::createLimitRequirement(limitEnum, limitValue);
 	}
+	else if (m_curTokenStr == "full_glsl_es_100_support")
+	{
+		advanceToken();
+
+		valueBlock = ShaderCase::CaseRequirement::createFullGLSLES100SpecificationRequirement();
+	}
 	else
 		parseError(string("invalid requirement value: " + m_curTokenStr));
 }
diff --git a/modules/glshared/glsShaderLibraryCase.cpp b/modules/glshared/glsShaderLibraryCase.cpp
index af30141..089d7a6 100644
--- a/modules/glshared/glsShaderLibraryCase.cpp
+++ b/modules/glshared/glsShaderLibraryCase.cpp
@@ -121,6 +121,15 @@
 	return retVal;
 }
 
+ShaderCase::CaseRequirement ShaderCase::CaseRequirement::createFullGLSLES100SpecificationRequirement (void)
+{
+	CaseRequirement retVal;
+
+	retVal.m_type = REQUIREMENTTYPE_FULL_GLSL_ES_100_SPEC;
+
+	return retVal;
+}
+
 void ShaderCase::CaseRequirement::checkRequirements (glu::RenderContext& renderCtx, const glu::ContextInfo& contextInfo)
 {
 	DE_UNREF(renderCtx);
@@ -176,6 +185,12 @@
 			return;
 		}
 
+		case REQUIREMENTTYPE_FULL_GLSL_ES_100_SPEC:
+		{
+			// cannot be queried
+			return;
+		}
+
 		default:
 			DE_ASSERT(false);
 	}
@@ -495,6 +510,19 @@
 			DE_ASSERT(false);
 			break;
 	}
+
+	// sanity of arguments
+
+	if (anyProgramRequiresFullGLSLES100Specification())
+	{
+		// makes only sense in tests where shader compiles
+		DE_ASSERT(m_expectResult == EXPECT_PASS				||
+				  m_expectResult == EXPECT_VALIDATION_FAIL	||
+				  m_expectResult == EXPECT_BUILD_SUCCESSFUL);
+
+		// only makes sense for ES 100 programs
+		DE_ASSERT(m_targetVersion == glu::GLSL_VERSION_100_ES);
+	}
 }
 
 static void setUniformValue (const glw::Functions& gl, const std::vector<deUint32>& pipelinePrograms, const std::string& name, const ShaderCase::Value& val, int arrayNdx, tcu::TestLog& log)
@@ -576,6 +604,17 @@
 				!m_programs[0].programSources.sources[glu::SHADERTYPE_TESSELLATION_EVALUATION].empty();
 }
 
+bool ShaderCase::anyProgramRequiresFullGLSLES100Specification (void) const
+{
+	for (int programNdx = 0; programNdx < (int)m_programs.size(); ++programNdx)
+	for (int requirementNdx = 0; requirementNdx < (int)m_programs[programNdx].spec.requirements.size(); ++requirementNdx)
+	{
+		if (m_programs[programNdx].spec.requirements[requirementNdx].getType() == CaseRequirement::REQUIREMENTTYPE_FULL_GLSL_ES_100_SPEC)
+			return true;
+	}
+	return false;
+}
+
 bool ShaderCase::checkPixels (Surface& surface, int minX, int maxX, int minY, int maxY)
 {
 	TestLog&	log				= m_testCtx.getLog();
@@ -615,8 +654,8 @@
 
 bool ShaderCase::execute (void)
 {
-	const float										quadSize			= 1.0f;
-	static const float								s_positions[4*4]	=
+	const float										quadSize				= 1.0f;
+	static const float								s_positions[4*4]		=
 	{
 		-quadSize, -quadSize, 0.0f, 1.0f,
 		-quadSize, +quadSize, 0.0f, 1.0f,
@@ -624,30 +663,31 @@
 		+quadSize, +quadSize, 0.0f, 1.0f
 	};
 
-	static const deUint16							s_indices[2*3]		=
+	static const deUint16							s_indices[2*3]			=
 	{
 		0, 1, 2,
 		1, 3, 2
 	};
 
-	TestLog&										log					= m_testCtx.getLog();
-	const glw::Functions&							gl					= m_renderCtx.getFunctions();
+	TestLog&										log						= m_testCtx.getLog();
+	const glw::Functions&							gl						= m_renderCtx.getFunctions();
 
 	// Compute viewport.
-	const tcu::RenderTarget&						renderTarget		= m_renderCtx.getRenderTarget();
-	de::Random										rnd					(deStringHash(getName()));
-	const int										width				= deMin32(renderTarget.getWidth(),	VIEWPORT_WIDTH);
-	const int										height				= deMin32(renderTarget.getHeight(),	VIEWPORT_HEIGHT);
-	const int										viewportX			= rnd.getInt(0, renderTarget.getWidth()  - width);
-	const int										viewportY			= rnd.getInt(0, renderTarget.getHeight() - height);
-	const int										numVerticesPerDraw	= 4;
-	const bool										tessellationPresent	= isTessellationPresent();
+	const tcu::RenderTarget&						renderTarget			= m_renderCtx.getRenderTarget();
+	de::Random										rnd						(deStringHash(getName()));
+	const int										width					= deMin32(renderTarget.getWidth(),	VIEWPORT_WIDTH);
+	const int										height					= deMin32(renderTarget.getHeight(),	VIEWPORT_HEIGHT);
+	const int										viewportX				= rnd.getInt(0, renderTarget.getWidth()  - width);
+	const int										viewportY				= rnd.getInt(0, renderTarget.getHeight() - height);
+	const int										numVerticesPerDraw		= 4;
+	const bool										tessellationPresent		= isTessellationPresent();
+	const bool										requiresFullGLSLES100	= anyProgramRequiresFullGLSLES100Specification();
 
-	bool											allCompilesOk		= true;
-	bool											allLinksOk			= true;
-	const char*										failReason			= DE_NULL;
+	bool											allCompilesOk			= true;
+	bool											allLinksOk				= true;
+	const char*										failReason				= DE_NULL;
 
-	deUint32										vertexProgramID		= -1;
+	deUint32										vertexProgramID			= -1;
 	std::vector<deUint32>							pipelineProgramIDs;
 	std::vector<de::SharedPtr<glu::ShaderProgram> >	programs;
 	de::SharedPtr<glu::ProgramPipeline>				programPipeline;
@@ -761,9 +801,26 @@
 		// \todo [2010-06-07 petri] These should be handled in the test case?
 		log << TestLog::Message << "ERROR: " << failReason << TestLog::EndMessage;
 
-		// If implementation parses shader at link time, report it as quality warning.
-		if (m_expectResult == EXPECT_COMPILE_FAIL && allCompilesOk && !allLinksOk)
+		if (requiresFullGLSLES100)
+		{
+			log	<< TestLog::Message
+				<< "Assuming build failure is caused by implementation not supporting full GLSL ES 100 specification, which is not required."
+				<< TestLog::EndMessage;
+
+			if (allCompilesOk && !allLinksOk)
+			{
+				// Used features are detectable at compile time. If implementation parses shader
+				// at link time, report it as quality warning.
+				m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, failReason);
+			}
+			else
+				m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Full GLSL ES 100 is not supported");
+		}
+		else if (m_expectResult == EXPECT_COMPILE_FAIL && allCompilesOk && !allLinksOk)
+		{
+			// If implementation parses shader at link time, report it as quality warning.
 			m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, failReason);
+		}
 		else
 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, failReason);
 		return false;
@@ -774,7 +831,7 @@
 		m_expectResult == EXPECT_COMPILE_LINK_FAIL	||
 		m_expectResult == EXPECT_LINK_FAIL			||
 		m_expectResult == EXPECT_BUILD_SUCCESSFUL)
-		return (failReason == DE_NULL);
+		return true;
 
 	// Setup viewport.
 	gl.viewport(viewportX, viewportY, width, height);
diff --git a/modules/glshared/glsShaderLibraryCase.hpp b/modules/glshared/glsShaderLibraryCase.hpp
index 8934c98..162ea0f 100644
--- a/modules/glshared/glsShaderLibraryCase.hpp
+++ b/modules/glshared/glsShaderLibraryCase.hpp
@@ -107,19 +107,21 @@
 		{
 			REQUIREMENTTYPE_EXTENSION = 0,
 			REQUIREMENTTYPE_IMPLEMENTATION_LIMIT,
+			REQUIREMENTTYPE_FULL_GLSL_ES_100_SPEC,	//!< Full support (as opposed to limited as specified for GLES 2.0 (See GLSL Appendix A)) cannot be queried
 
 			REQUIREMENTTYPE_LAST
 		};
 
-									CaseRequirement					(void);
+									CaseRequirement								(void);
 
-		static CaseRequirement		createAnyExtensionRequirement	(const std::vector<std::string>& requirements, deUint32 effectiveShaderStageFlags);
-		static CaseRequirement		createLimitRequirement			(deUint32 enumName, int ref);
-		void						checkRequirements				(glu::RenderContext& renderCtx, const glu::ContextInfo& contextInfo);
+		static CaseRequirement		createAnyExtensionRequirement				(const std::vector<std::string>& requirements, deUint32 effectiveShaderStageFlags);
+		static CaseRequirement		createLimitRequirement						(deUint32 enumName, int ref);
+		static CaseRequirement		createFullGLSLES100SpecificationRequirement	(void);
+		void						checkRequirements							(glu::RenderContext& renderCtx, const glu::ContextInfo& contextInfo);
 
-		RequirementType				getType							(void) const { return m_type; };
-		std::string					getSupportedExtension			(void) const { DE_ASSERT(m_type == REQUIREMENTTYPE_EXTENSION); DE_ASSERT(m_supportedExtensionNdx >= 0); return m_extensions[m_supportedExtensionNdx]; }
-		deUint32					getAffectedExtensionStageFlags	(void) const { DE_ASSERT(m_type == REQUIREMENTTYPE_EXTENSION); return m_effectiveShaderStageFlags; }
+		RequirementType				getType										(void) const { return m_type; };
+		std::string					getSupportedExtension						(void) const { DE_ASSERT(m_type == REQUIREMENTTYPE_EXTENSION); DE_ASSERT(m_supportedExtensionNdx >= 0); return m_extensions[m_supportedExtensionNdx]; }
+		deUint32					getAffectedExtensionStageFlags				(void) const { DE_ASSERT(m_type == REQUIREMENTTYPE_EXTENSION); return m_effectiveShaderStageFlags; }
 
 	private:
 		RequirementType				m_type;
@@ -174,42 +176,43 @@
 	};
 
 	// Methods.
-									ShaderCase						(tcu::TestContext&				testCtx,
-																	 glu::RenderContext&			renderCtx,
-																	 const glu::ContextInfo&		contextInfo,
-																	 const char*					caseName,
-																	 const char*					description,
-																	 const ShaderCaseSpecification&	specification);
-									ShaderCase						(tcu::TestContext&					testCtx,
-																	 glu::RenderContext&				renderCtx,
-																	 const glu::ContextInfo&			contextInfo,
-																	 const char*						caseName,
-																	 const char*						description,
-																	 const PipelineCaseSpecification&	specification);
-	virtual							~ShaderCase						(void);
+									ShaderCase										(tcu::TestContext&				testCtx,
+																					 glu::RenderContext&			renderCtx,
+																					 const glu::ContextInfo&		contextInfo,
+																					 const char*					caseName,
+																					 const char*					description,
+																					 const ShaderCaseSpecification&	specification);
+									ShaderCase										(tcu::TestContext&					testCtx,
+																					 glu::RenderContext&				renderCtx,
+																					 const glu::ContextInfo&			contextInfo,
+																					 const char*						caseName,
+																					 const char*						description,
+																					 const PipelineCaseSpecification&	specification);
+	virtual							~ShaderCase										(void);
 
 private:
-	void							init							(void);
-	bool							execute							(void);
-	IterateResult					iterate							(void);
+	void							init											(void);
+	bool							execute											(void);
+	IterateResult					iterate											(void);
 
-									ShaderCase						(const ShaderCase&);		// not allowed!
-	ShaderCase&						operator=						(const ShaderCase&);		// not allowed!
+									ShaderCase										(const ShaderCase&);		// not allowed!
+	ShaderCase&						operator=										(const ShaderCase&);		// not allowed!
 
-	std::string						genVertexShader					(const ValueBlock& valueBlock) const;
-	std::string						genFragmentShader				(const ValueBlock& valueBlock) const;
-	std::string						specializeVertexShader			(const char* src, const ValueBlock& valueBlock) const;
-	std::string						specializeFragmentShader		(const char* src, const ValueBlock& valueBlock) const;
-	void							specializeVertexShaders			(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
-	void							specializeFragmentShaders		(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
-	void							specializeGeometryShaders		(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
-	void							specializeTessControlShaders	(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
-	void							specializeTessEvalShaders		(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
-	bool							isTessellationPresent			(void) const;
+	std::string						genVertexShader									(const ValueBlock& valueBlock) const;
+	std::string						genFragmentShader								(const ValueBlock& valueBlock) const;
+	std::string						specializeVertexShader							(const char* src, const ValueBlock& valueBlock) const;
+	std::string						specializeFragmentShader						(const char* src, const ValueBlock& valueBlock) const;
+	void							specializeVertexShaders							(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
+	void							specializeFragmentShaders						(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
+	void							specializeGeometryShaders						(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
+	void							specializeTessControlShaders					(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
+	void							specializeTessEvalShaders						(glu::ProgramSources& dst, const std::vector<std::string>& sources, const ValueBlock& valueBlock, const std::vector<ShaderCase::CaseRequirement>& requirements) const;
+	bool							isTessellationPresent							(void) const;
+	bool							anyProgramRequiresFullGLSLES100Specification	(void) const;
 
-	void							dumpValues						(const ValueBlock& valueBlock, int arrayNdx);
+	void							dumpValues										(const ValueBlock& valueBlock, int arrayNdx);
 
-	bool 							checkPixels						(tcu::Surface& surface, int minX, int maxX, int minY, int maxY);
+	bool 							checkPixels										(tcu::Surface& surface, int minX, int maxX, int minY, int maxY);
 
 	struct ProgramObject
 	{