Merge "Allow dynamic loop cases to fail on GLSL ES 100."
diff --git a/data/gles2/shaders/functions.test b/data/gles2/shaders/functions.test
index 3f03112..6469b98 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
 	{