Merge "DO NOT MERGE: GetDevices: Also allow `\-` to be part of the host name"
diff --git a/framework/platform/android/tcuAndroidRenderActivity.cpp b/framework/platform/android/tcuAndroidRenderActivity.cpp
index ddbf40e..0c3bd19 100644
--- a/framework/platform/android/tcuAndroidRenderActivity.cpp
+++ b/framework/platform/android/tcuAndroidRenderActivity.cpp
@@ -78,6 +78,7 @@
 	, m_window			(DE_NULL)
 	, m_paused			(false)
 	, m_finish			(false)
+	, m_receivedFirstResize(false)
 {
 }
 
@@ -143,7 +144,29 @@
 			if (m_windowState != WINDOWSTATE_NOT_CREATED && m_windowState != WINDOWSTATE_DESTROYED)
 				throw InternalError("Got unexpected onNativeWindowCreated() event from system");
 
-			m_windowState	= WINDOWSTATE_NOT_INITIALIZED;
+			// The documented behavior for the callbacks is that the native activity
+			// will get a call to onNativeWindowCreated(), at which point it should have
+			// a surface to render to, and can then start immediately.
+			//
+			// The actual creation process has the framework making calls to both
+			// onNativeWindowCreated() and then onNativeWindowResized(). The test
+			// waits for that first resize before it considers the window ready for
+			// rendering.
+			//
+			// However subsequent events in the framework may cause the window to be
+			// recreated at a new position without a size change, which sends on
+			// onNativeWindowDestroyed(), and then on onNativeWindowCreated() without
+			// a follow-up onNativeWindowResized(). If this happens, the test will
+			// stop rendering as it is no longer in the ready state, and a watchdog
+			// thread will eventually kill the test, causing it to fail. We therefore
+			// set the window state back to READY and process the window creation here
+			// if we have already observed that first resize call.
+			if (!m_receivedFirstResize) {
+				m_windowState	= WINDOWSTATE_NOT_INITIALIZED;
+			} else {
+				m_windowState	= WINDOWSTATE_READY;
+				onWindowCreated(message.payload.window);
+			}
 			m_window		= message.payload.window;
 			break;
 
@@ -151,6 +174,10 @@
 			if (m_window != message.payload.window)
 				throw InternalError("Got onNativeWindowResized() event targeting different window");
 
+			// Record that we've the first resize event, in case the window is
+			// recreated later without a resize.
+			m_receivedFirstResize = true;
+
 			if (m_windowState == WINDOWSTATE_NOT_INITIALIZED)
 			{
 				// Got first resize event, window is ready for use.
diff --git a/framework/platform/android/tcuAndroidRenderActivity.hpp b/framework/platform/android/tcuAndroidRenderActivity.hpp
index e2e7331..9cad495 100644
--- a/framework/platform/android/tcuAndroidRenderActivity.hpp
+++ b/framework/platform/android/tcuAndroidRenderActivity.hpp
@@ -158,6 +158,7 @@
 	ANativeWindow*			m_window;
 	bool					m_paused;					//!< Is rendering paused?
 	bool					m_finish;					//!< Has thread received FINISH message?
+	bool					m_receivedFirstResize;				//!< Has the first onWindowResized been processed?
 };
 
 class RenderActivity : public NativeActivity
diff --git a/modules/gles2/functional/es2fTextureSizeTests.cpp b/modules/gles2/functional/es2fTextureSizeTests.cpp
index f7627b9..dbf2776 100644
--- a/modules/gles2/functional/es2fTextureSizeTests.cpp
+++ b/modules/gles2/functional/es2fTextureSizeTests.cpp
@@ -124,7 +124,7 @@
 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
 	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
 	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
-	const tcu::PixelFormat	thresholdFormat(std::min(texBits[0], rtFmt.redBits), std::min(texBits[1], rtFmt.greenBits), std::min(texBits[2], rtFmt.blueBits), std::min(texBits[3], rtFmt.alphaBits));
+	const tcu::PixelFormat	thresholdFormat(de::min(texBits[0], rtFmt.redBits), de::min(texBits[1], rtFmt.greenBits), de::min(texBits[2], rtFmt.blueBits), de::min(texBits[3], rtFmt.alphaBits));
 	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;
@@ -270,7 +270,7 @@
 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
 	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
 	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
-	const tcu::PixelFormat	thresholdFormat(std::min(texBits[0], rtFmt.redBits), std::min(texBits[1], rtFmt.greenBits), std::min(texBits[2], rtFmt.blueBits), std::min(texBits[3], rtFmt.alphaBits));
+	const tcu::PixelFormat	thresholdFormat(de::min(texBits[0], rtFmt.redBits), de::min(texBits[1], rtFmt.greenBits), de::min(texBits[2], rtFmt.blueBits), de::min(texBits[3], rtFmt.alphaBits));
 	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;
diff --git a/modules/gles3/functional/es3fShaderDerivateTests.cpp b/modules/gles3/functional/es3fShaderDerivateTests.cpp
index 70e61b4..15013bf 100644
--- a/modules/gles3/functional/es3fShaderDerivateTests.cpp
+++ b/modules/gles3/functional/es3fShaderDerivateTests.cpp
@@ -214,7 +214,7 @@
 {
 	const int		numGarbageBits	= 23-numAccurateBits;
 	const deUint32	mask			= (1u<<numGarbageBits)-1u;
-	const int		exp				= tcu::Float32(value).exponent();
+	const int		exp				= (tcu::Float32(value).exponent() < -3) ? -3 : tcu::Float32(value).exponent();
 
 	return tcu::Float32::construct(+1, exp, (1u<<23) | mask).asFloat() - tcu::Float32::construct(+1, exp, 1u<<23).asFloat();
 }
@@ -323,6 +323,20 @@
 	INTERPOLATION_LOST_BITS = 3, // number mantissa of bits allowed to be lost in varying interpolation
 };
 
+static int getInterpolationLostBitsWarning (const glu::Precision precision)
+{
+	// number mantissa of bits allowed to be lost in varying interpolation
+	switch (precision)
+	{
+		case glu::PRECISION_HIGHP:		return 9;
+		case glu::PRECISION_MEDIUMP:	return 3;
+		case glu::PRECISION_LOWP:		return 3;
+		default:
+			DE_ASSERT(false);
+			return 0;
+	}
+}
+
 static inline tcu::Vec4 getDerivateThreshold (const glu::Precision precision, const tcu::Vec4& valueMin, const tcu::Vec4& valueMax, const tcu::Vec4& expectedDerivate)
 {
 	const int			baseBits		= getNumMantissaBits(precision);
@@ -337,6 +351,21 @@
 					 computeFloatingPointError(expectedDerivate[3], numAccurateBits[3]));
 }
 
+static inline tcu::Vec4 getDerivateThresholdWarning (const glu::Precision precision, const tcu::Vec4& valueMin, const tcu::Vec4& valueMax, const tcu::Vec4& expectedDerivate)
+{
+	const int			baseBits		= getNumMantissaBits(precision);
+	const tcu::UVec4	derivExp		= getCompExpBits(expectedDerivate);
+	const tcu::UVec4	maxValueExp		= max(getCompExpBits(valueMin), getCompExpBits(valueMax));
+	const tcu::UVec4	numBitsLost		= maxValueExp - min(maxValueExp, derivExp);
+	const tcu::IVec4	numAccurateBits	= max(baseBits - numBitsLost.asInt() - getInterpolationLostBitsWarning(precision), tcu::IVec4(0));
+
+	return tcu::Vec4(computeFloatingPointError(expectedDerivate[0], numAccurateBits[0]),
+					 computeFloatingPointError(expectedDerivate[1], numAccurateBits[1]),
+					 computeFloatingPointError(expectedDerivate[2], numAccurateBits[2]),
+					 computeFloatingPointError(expectedDerivate[3], numAccurateBits[3]));
+}
+
+
 namespace
 {
 
@@ -369,7 +398,7 @@
 	LOG_NOTHING
 };
 
-static bool verifyConstantDerivate (tcu::TestLog&						log,
+static qpTestResult verifyConstantDerivate (tcu::TestLog&				log,
 									const tcu::ConstPixelBufferAccess&	result,
 									const tcu::PixelBufferAccess&		errorMask,
 									glu::DataType						dataType,
@@ -412,7 +441,7 @@
 	if (numFailedPixels > 0 && logPolicy == LOG_ALL)
 		log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage;
 
-	return numFailedPixels == 0;
+	return (numFailedPixels == 0) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL;
 }
 
 struct Linear2DFunctionEvaluator
@@ -433,7 +462,7 @@
 	return matrix * position;
 }
 
-static bool reverifyConstantDerivateWithFlushRelaxations (tcu::TestLog&							log,
+static qpTestResult reverifyConstantDerivateWithFlushRelaxations (tcu::TestLog&							log,
 														  const tcu::ConstPixelBufferAccess&	result,
 														  const tcu::PixelBufferAccess&			errorMask,
 														  glu::DataType							dataType,
@@ -551,7 +580,7 @@
 	if (numFailedPixels > 0)
 		log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage;
 
-	return numFailedPixels == 0;
+	return (numFailedPixels == 0) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL;
 }
 
 // TriangleDerivateCase
@@ -559,34 +588,34 @@
 class TriangleDerivateCase : public TestCase
 {
 public:
-						TriangleDerivateCase	(Context& context, const char* name, const char* description);
-						~TriangleDerivateCase	(void);
+							TriangleDerivateCase	(Context& context, const char* name, const char* description);
+							~TriangleDerivateCase	(void);
 
-	IterateResult		iterate					(void);
+	IterateResult			iterate					(void);
 
 protected:
-	virtual void		setupRenderState		(deUint32 program) { DE_UNREF(program); }
-	virtual bool		verify					(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) = DE_NULL;
+	virtual void			setupRenderState		(deUint32 program) { DE_UNREF(program); }
+	virtual qpTestResult	verify					(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) = DE_NULL;
 
-	tcu::IVec2			getViewportSize			(void) const;
-	tcu::Vec4			getSurfaceThreshold		(void) const;
+	tcu::IVec2				getViewportSize			(void) const;
+	tcu::Vec4				getSurfaceThreshold		(void) const;
 
-	glu::DataType		m_dataType;
-	glu::Precision		m_precision;
+	glu::DataType			m_dataType;
+	glu::Precision			m_precision;
 
-	glu::DataType		m_coordDataType;
-	glu::Precision		m_coordPrecision;
+	glu::DataType			m_coordDataType;
+	glu::Precision			m_coordPrecision;
 
-	std::string			m_fragmentSrc;
+	std::string				m_fragmentSrc;
 
-	tcu::Vec4			m_coordMin;
-	tcu::Vec4			m_coordMax;
-	tcu::Vec4			m_derivScale;
-	tcu::Vec4			m_derivBias;
+	tcu::Vec4				m_coordMin;
+	tcu::Vec4				m_coordMax;
+	tcu::Vec4				m_derivScale;
+	tcu::Vec4				m_derivBias;
 
-	SurfaceType			m_surfaceType;
-	int					m_numSamples;
-	deUint32			m_hint;
+	SurfaceType				m_surfaceType;
+	int						m_numSamples;
+	deUint32				m_hint;
 };
 
 TriangleDerivateCase::TriangleDerivateCase (Context& context, const char* name, const char* description)
@@ -825,18 +854,24 @@
 		tcu::Surface errorMask(result.getWidth(), result.getHeight());
 		tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
 
-		const bool isOk = verify(result.getAccess(), errorMask.getAccess());
+		const qpTestResult testResult = verify(result.getAccess(), errorMask.getAccess());
+		const char* failStr = "Fail";
 
 		m_testCtx.getLog() << TestLog::ImageSet("Result", "Result images")
 						   << TestLog::Image("Rendered", "Rendered image", result);
 
-		if (!isOk)
+		if (testResult != QP_TEST_RESULT_PASS)
 			m_testCtx.getLog() << TestLog::Image("ErrorMask", "Error mask", errorMask);
 
 		m_testCtx.getLog() << TestLog::EndImageSet;
 
-		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
-								isOk ? "Pass"				: "Image comparison failed");
+		if (testResult == QP_TEST_RESULT_PASS)
+			failStr = "Pass";
+		else if (testResult == QP_TEST_RESULT_QUALITY_WARNING)
+			failStr = "QualityWarning";
+
+		m_testCtx.setTestResult(testResult, failStr);
+
 	}
 
 	return STOP;
@@ -875,7 +910,7 @@
 	void				init						(void);
 
 protected:
-	bool				verify						(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask);
+	qpTestResult		verify						(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask);
 
 private:
 	DerivateFunc		m_func;
@@ -922,7 +957,7 @@
 	m_derivBias		= tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
 }
 
-bool ConstantDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)
+qpTestResult ConstantDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)
 {
 	const tcu::Vec4 reference	(0.0f); // Derivate of constant argument should always be 0
 	const tcu::Vec4	threshold	= getSurfaceThreshold() / abs(m_derivScale);
@@ -942,7 +977,7 @@
 	void				init					(void);
 
 protected:
-	bool				verify					(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask);
+	qpTestResult		verify					(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask);
 
 private:
 	DerivateFunc		m_func;
@@ -1049,7 +1084,7 @@
 	}
 }
 
-bool LinearDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)
+qpTestResult LinearDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)
 {
 	const tcu::Vec4		xScale				= tcu::Vec4(1.0f, 0.0f, 0.5f, -0.5f);
 	const tcu::Vec4		yScale				= tcu::Vec4(0.0f, 1.0f, 0.5f, -0.5f);
@@ -1057,13 +1092,15 @@
 
 	if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY)
 	{
-		const bool			isX			= m_func == DERIVATE_DFDX;
-		const float			div			= isX ? float(result.getWidth()) : float(result.getHeight());
-		const tcu::Vec4		scale		= isX ? xScale : yScale;
-		const tcu::Vec4		reference	= ((m_coordMax - m_coordMin) / div) * scale;
-		const tcu::Vec4		opThreshold	= getDerivateThreshold(m_precision, m_coordMin*scale, m_coordMax*scale, reference);
-		const tcu::Vec4		threshold	= max(surfaceThreshold, opThreshold);
-		const int			numComps	= glu::getDataTypeFloatScalars(m_dataType);
+		const bool			isX				= m_func == DERIVATE_DFDX;
+		const float			div				= isX ? float(result.getWidth()) : float(result.getHeight());
+		const tcu::Vec4		scale			= isX ? xScale : yScale;
+		const tcu::Vec4		reference		= ((m_coordMax - m_coordMin) / div) * scale;
+		const tcu::Vec4		opThreshold		= getDerivateThreshold(m_precision, m_coordMin*scale, m_coordMax*scale, reference);
+		const tcu::Vec4		opThresholdW	= getDerivateThresholdWarning(m_precision, m_coordMin*scale, m_coordMax*scale, reference);
+		const tcu::Vec4		threshold		= max(surfaceThreshold, opThreshold);
+		const tcu::Vec4		thresholdW		= max(surfaceThreshold, opThresholdW);
+		const int			numComps		= glu::getDataTypeFloatScalars(m_dataType);
 
 		m_testCtx.getLog()
 			<< tcu::TestLog::Message
@@ -1075,14 +1112,27 @@
 		// This improves performance significantly.
 		if (verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType,
 								   reference, threshold, m_derivScale, m_derivBias,
-								   LOG_NOTHING))
+								   LOG_NOTHING) == QP_TEST_RESULT_PASS)
 		{
 			m_testCtx.getLog()
 				<< tcu::TestLog::Message
 				<< "No incorrect derivatives found, result valid."
 				<< tcu::TestLog::EndMessage;
 
-			return true;
+			return QP_TEST_RESULT_PASS;
+		}
+
+		// Check with relaxed threshold value
+		if (verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType,
+								   reference, thresholdW, m_derivScale, m_derivBias,
+								   LOG_NOTHING) == QP_TEST_RESULT_PASS)
+		{
+			m_testCtx.getLog()
+				<< tcu::TestLog::Message
+				<< "No incorrect derivatives found, result valid with quality warning."
+				<< tcu::TestLog::EndMessage;
+
+			return QP_TEST_RESULT_QUALITY_WARNING;
 		}
 
 		// some pixels exceed error bounds calculated for normal values. Verify that these
@@ -1115,18 +1165,36 @@
 	else
 	{
 		DE_ASSERT(m_func == DERIVATE_FWIDTH);
-		const float			w			= float(result.getWidth());
-		const float			h			= float(result.getHeight());
+		const float			w				= float(result.getWidth());
+		const float			h				= float(result.getHeight());
 
-		const tcu::Vec4		dx			= ((m_coordMax - m_coordMin) / w) * xScale;
-		const tcu::Vec4		dy			= ((m_coordMax - m_coordMin) / h) * yScale;
-		const tcu::Vec4		reference	= tcu::abs(dx) + tcu::abs(dy);
-		const tcu::Vec4		dxThreshold	= getDerivateThreshold(m_precision, m_coordMin*xScale, m_coordMax*xScale, dx);
-		const tcu::Vec4		dyThreshold	= getDerivateThreshold(m_precision, m_coordMin*yScale, m_coordMax*yScale, dy);
-		const tcu::Vec4		threshold	= max(surfaceThreshold, max(dxThreshold, dyThreshold));
+		const tcu::Vec4		dx				= ((m_coordMax - m_coordMin) / w) * xScale;
+		const tcu::Vec4		dy				= ((m_coordMax - m_coordMin) / h) * yScale;
+		const tcu::Vec4		reference		= tcu::abs(dx) + tcu::abs(dy);
+		const tcu::Vec4		dxThreshold		= getDerivateThreshold(m_precision, m_coordMin*xScale, m_coordMax*xScale, dx);
+		const tcu::Vec4		dyThreshold		= getDerivateThreshold(m_precision, m_coordMin*yScale, m_coordMax*yScale, dy);
+		const tcu::Vec4		dxThresholdW	= getDerivateThresholdWarning(m_precision, m_coordMin*xScale, m_coordMax*xScale, dx);
+		const tcu::Vec4		dyThresholdW	= getDerivateThresholdWarning(m_precision, m_coordMin*yScale, m_coordMax*yScale, dy);
+		const tcu::Vec4		threshold		= max(surfaceThreshold, max(dxThreshold, dyThreshold));
+		const tcu::Vec4		thresholdW		= max(surfaceThreshold, max(dxThresholdW, dyThresholdW));
+		qpTestResult        testResult		= QP_TEST_RESULT_FAIL;
 
-		return verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType,
+		testResult = verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType,
 									  reference, threshold, m_derivScale, m_derivBias);
+
+		// return if result is pass
+		if (testResult == QP_TEST_RESULT_PASS)
+			return testResult;
+
+		// re-check with relaxed threshold
+		testResult = verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType,
+									  reference, thresholdW, m_derivScale, m_derivBias);
+
+		// if with relaxed threshold test is passing then mark the result with quality warning.
+		if (testResult == QP_TEST_RESULT_PASS)
+			testResult = QP_TEST_RESULT_QUALITY_WARNING;
+
+		return testResult;
 	}
 }
 
@@ -1143,7 +1211,7 @@
 
 protected:
 	void				setupRenderState		(deUint32 program);
-	bool				verify					(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask);
+	qpTestResult		verify					(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask);
 
 private:
 	DerivateFunc		m_func;
@@ -1335,7 +1403,7 @@
 	gl.uniform1i		(gl.getUniformLocation(program, "u_sampler"), texUnit);
 }
 
-bool TextureDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)
+qpTestResult TextureDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)
 {
 	// \note Edges are ignored in comparison
 	if (result.getWidth() < 2 || result.getHeight() < 2)
@@ -1352,13 +1420,15 @@
 
 	if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY)
 	{
-		const bool			isX			= m_func == DERIVATE_DFDX;
-		const float			div			= isX ? w : h;
-		const tcu::Vec4		scale		= isX ? xScale : yScale;
-		const tcu::Vec4		reference	= ((m_texValueMax - m_texValueMin) / div) * scale;
-		const tcu::Vec4		opThreshold	= getDerivateThreshold(m_precision, m_texValueMin*scale, m_texValueMax*scale, reference);
-		const tcu::Vec4		threshold	= max(surfaceThreshold, opThreshold);
-		const int			numComps	= glu::getDataTypeFloatScalars(m_dataType);
+		const bool			isX				= m_func == DERIVATE_DFDX;
+		const float			div				= isX ? w : h;
+		const tcu::Vec4		scale			= isX ? xScale : yScale;
+		const tcu::Vec4		reference		= ((m_texValueMax - m_texValueMin) / div) * scale;
+		const tcu::Vec4		opThreshold		= getDerivateThreshold(m_precision, m_texValueMin*scale, m_texValueMax*scale, reference);
+		const tcu::Vec4		opThresholdW	= getDerivateThresholdWarning(m_precision, m_texValueMin*scale, m_texValueMax*scale, reference);
+		const tcu::Vec4		threshold		= max(surfaceThreshold, opThreshold);
+		const tcu::Vec4		thresholdW		= max(surfaceThreshold, opThresholdW);
+		const int			numComps		= glu::getDataTypeFloatScalars(m_dataType);
 
 		m_testCtx.getLog()
 			<< tcu::TestLog::Message
@@ -1370,16 +1440,36 @@
 		// This improves performance significantly.
 		if (verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType,
 								   reference, threshold, m_derivScale, m_derivBias,
-								   LOG_NOTHING))
+								   LOG_NOTHING) == QP_TEST_RESULT_PASS)
 		{
 			m_testCtx.getLog()
 				<< tcu::TestLog::Message
 				<< "No incorrect derivatives found, result valid."
 				<< tcu::TestLog::EndMessage;
 
-			return true;
+			return QP_TEST_RESULT_PASS;
 		}
 
+		m_testCtx.getLog()
+			<< tcu::TestLog::Message
+			<< "Verifying result image.\n"
+			<< "\tValid derivative is " << LogVecComps(reference, numComps) << " with Warning threshold " << LogVecComps(thresholdW, numComps)
+			<< tcu::TestLog::EndMessage;
+
+		// Re-check with relaxed threshold
+		if (verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType,
+								   reference, thresholdW, m_derivScale, m_derivBias,
+								   LOG_NOTHING) == QP_TEST_RESULT_PASS)
+		{
+			m_testCtx.getLog()
+				<< tcu::TestLog::Message
+				<< "No incorrect derivatives found, result valid with quality warning."
+				<< tcu::TestLog::EndMessage;
+
+			return QP_TEST_RESULT_QUALITY_WARNING;
+		}
+
+
 		// some pixels exceed error bounds calculated for normal values. Verify that these
 		// potentially invalid pixels are in fact valid due to (for example) subnorm flushing.
 
@@ -1407,15 +1497,32 @@
 	else
 	{
 		DE_ASSERT(m_func == DERIVATE_FWIDTH);
-		const tcu::Vec4	dx			= ((m_texValueMax - m_texValueMin) / w) * xScale;
-		const tcu::Vec4	dy			= ((m_texValueMax - m_texValueMin) / h) * yScale;
-		const tcu::Vec4	reference	= tcu::abs(dx) + tcu::abs(dy);
-		const tcu::Vec4	dxThreshold	= getDerivateThreshold(m_precision, m_texValueMin*xScale, m_texValueMax*xScale, dx);
-		const tcu::Vec4	dyThreshold	= getDerivateThreshold(m_precision, m_texValueMin*yScale, m_texValueMax*yScale, dy);
-		const tcu::Vec4	threshold	= max(surfaceThreshold, max(dxThreshold, dyThreshold));
+		const tcu::Vec4	dx				= ((m_texValueMax - m_texValueMin) / w) * xScale;
+		const tcu::Vec4	dy				= ((m_texValueMax - m_texValueMin) / h) * yScale;
+		const tcu::Vec4	reference		= tcu::abs(dx) + tcu::abs(dy);
+		const tcu::Vec4	dxThreshold		= getDerivateThreshold(m_precision, m_texValueMin*xScale, m_texValueMax*xScale, dx);
+		const tcu::Vec4	dyThreshold		= getDerivateThreshold(m_precision, m_texValueMin*yScale, m_texValueMax*yScale, dy);
+		const tcu::Vec4	dxThresholdW	= getDerivateThresholdWarning(m_precision, m_texValueMin*xScale, m_texValueMax*xScale, dx);
+		const tcu::Vec4	dyThresholdW	= getDerivateThresholdWarning(m_precision, m_texValueMin*yScale, m_texValueMax*yScale, dy);
+		const tcu::Vec4	threshold		= max(surfaceThreshold, max(dxThreshold, dyThreshold));
+		const tcu::Vec4	thresholdW		= max(surfaceThreshold, max(dxThresholdW, dyThresholdW));
+		qpTestResult	testResult		= QP_TEST_RESULT_FAIL;
 
-		return verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType,
+		testResult = verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType,
 									  reference, threshold, m_derivScale, m_derivBias);
+
+		if (testResult == QP_TEST_RESULT_PASS)
+			return testResult;
+
+		// Re-Check with relaxed threshold
+		testResult = verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType,
+									  reference, thresholdW, m_derivScale, m_derivBias);
+
+		// If test is passing with relaxed threshold then mark quality warning
+		if (testResult == QP_TEST_RESULT_PASS)
+			testResult = QP_TEST_RESULT_QUALITY_WARNING;
+
+		return testResult;
 	}
 }
 
diff --git a/modules/gles3/functional/es3fTextureSizeTests.cpp b/modules/gles3/functional/es3fTextureSizeTests.cpp
index 6eeed5a..4e09fb5 100644
--- a/modules/gles3/functional/es3fTextureSizeTests.cpp
+++ b/modules/gles3/functional/es3fTextureSizeTests.cpp
@@ -125,7 +125,7 @@
 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
 	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
 	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
-	const tcu::PixelFormat	thresholdFormat(std::min(texBits[0], rtFmt.redBits), std::min(texBits[1], rtFmt.greenBits), std::min(texBits[2], rtFmt.blueBits), std::min(texBits[3], rtFmt.alphaBits));
+	const tcu::PixelFormat	thresholdFormat(de::min(texBits[0], rtFmt.redBits), de::min(texBits[1], rtFmt.greenBits), de::min(texBits[2], rtFmt.blueBits), de::min(texBits[3], rtFmt.alphaBits));
 	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;
@@ -271,7 +271,7 @@
 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
 	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
 	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
-	const tcu::PixelFormat	thresholdFormat(std::min(texBits[0], rtFmt.redBits), std::min(texBits[1], rtFmt.greenBits), std::min(texBits[2], rtFmt.blueBits), std::min(texBits[3], rtFmt.alphaBits));
+	const tcu::PixelFormat	thresholdFormat(de::min(texBits[0], rtFmt.redBits), de::min(texBits[1], rtFmt.greenBits), de::min(texBits[2], rtFmt.blueBits), de::min(texBits[3], rtFmt.alphaBits));
 	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;