/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Advanced blending (GL_KHR_blend_equation_advanced) tests.
 *//*--------------------------------------------------------------------*/

#include "es31fAdvancedBlendTests.hpp"
#include "gluStrUtil.hpp"
#include "glsFragmentOpUtil.hpp"
#include "glsStateQueryUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "gluObjectWrapper.hpp"
#include "gluContextInfo.hpp"
#include "gluShaderProgram.hpp"
#include "gluCallLogWrapper.hpp"
#include "gluStrUtil.hpp"
#include "tcuPixelFormat.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuTestLog.hpp"
#include "tcuStringTemplate.hpp"
#include "deRandom.hpp"
#include "deStringUtil.hpp"
#include "rrFragmentOperations.hpp"
#include "sglrReferenceUtils.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"

#include <string>
#include <vector>

namespace deqp
{

using gls::FragmentOpUtil::IntegerQuad;
using gls::FragmentOpUtil::ReferenceQuadRenderer;
using tcu::TextureLevel;
using tcu::Vec2;
using tcu::Vec4;
using tcu::UVec4;
using tcu::TestLog;
using tcu::TextureFormat;
using std::string;
using std::vector;
using std::map;

namespace gles31
{
namespace Functional
{

namespace
{

enum
{
	MAX_VIEWPORT_WIDTH		= 128,
	MAX_VIEWPORT_HEIGHT		= 128
};

enum RenderTargetType
{
	RENDERTARGETTYPE_DEFAULT	= 0,	//!< Default framebuffer
	RENDERTARGETTYPE_SRGB_FBO,
	RENDERTARGETTYPE_MSAA_FBO,

	RENDERTARGETTYPE_LAST
};

static const char* getEquationName (glw::GLenum equation)
{
	switch (equation)
	{
		case GL_MULTIPLY:		return "multiply";
		case GL_SCREEN:			return "screen";
		case GL_OVERLAY:		return "overlay";
		case GL_DARKEN:			return "darken";
		case GL_LIGHTEN:		return "lighten";
		case GL_COLORDODGE:		return "colordodge";
		case GL_COLORBURN:		return "colorburn";
		case GL_HARDLIGHT:		return "hardlight";
		case GL_SOFTLIGHT:		return "softlight";
		case GL_DIFFERENCE:		return "difference";
		case GL_EXCLUSION:		return "exclusion";
		case GL_HSL_HUE:		return "hsl_hue";
		case GL_HSL_SATURATION:	return "hsl_saturation";
		case GL_HSL_COLOR:		return "hsl_color";
		case GL_HSL_LUMINOSITY:	return "hsl_luminosity";
		default:
			DE_ASSERT(false);
			return DE_NULL;
	}
}

class AdvancedBlendCase : public TestCase
{
public:
							AdvancedBlendCase	(Context& context, const char* name, const char* desc, deUint32 mode, int overdrawCount, bool coherent, RenderTargetType rtType);

							~AdvancedBlendCase	(void);

	void					init				(void);
	void					deinit				(void);

	IterateResult			iterate		(void);

private:
							AdvancedBlendCase	(const AdvancedBlendCase&);
	AdvancedBlendCase&		operator=			(const AdvancedBlendCase&);

	const deUint32			m_blendMode;
	const int				m_overdrawCount;
	const bool				m_coherentBlending;
	const RenderTargetType	m_rtType;
	const int				m_numIters;

	bool					m_coherentExtensionSupported;

	deUint32				m_colorRbo;
	deUint32				m_fbo;

	deUint32				m_resolveColorRbo;
	deUint32				m_resolveFbo;

	glu::ShaderProgram*		m_program;

	ReferenceQuadRenderer*	m_referenceRenderer;
	TextureLevel*			m_refColorBuffer;

	const int				m_renderWidth;
	const int				m_renderHeight;
	const int				m_viewportWidth;
	const int				m_viewportHeight;

	int						m_iterNdx;
};

AdvancedBlendCase::AdvancedBlendCase (Context&			context,
									  const char*		name,
									  const char*		desc,
									  deUint32			mode,
									  int				overdrawCount,
									  bool				coherent,
									  RenderTargetType	rtType)
	: TestCase						(context, name, desc)
	, m_blendMode					(mode)
	, m_overdrawCount				(overdrawCount)
	, m_coherentBlending			(coherent)
	, m_rtType						(rtType)
	, m_numIters					(5)
	, m_coherentExtensionSupported	(false)
	, m_colorRbo					(0)
	, m_fbo							(0)
	, m_resolveColorRbo				(0)
	, m_resolveFbo					(0)
	, m_program						(DE_NULL)
	, m_referenceRenderer			(DE_NULL)
	, m_refColorBuffer				(DE_NULL)
	, m_renderWidth					(rtType != RENDERTARGETTYPE_DEFAULT ? 2*MAX_VIEWPORT_WIDTH	: m_context.getRenderTarget().getWidth())
	, m_renderHeight				(rtType != RENDERTARGETTYPE_DEFAULT ? 2*MAX_VIEWPORT_HEIGHT	: m_context.getRenderTarget().getHeight())
	, m_viewportWidth				(de::min<int>(m_renderWidth,	MAX_VIEWPORT_WIDTH))
	, m_viewportHeight				(de::min<int>(m_renderHeight,	MAX_VIEWPORT_HEIGHT))
	, m_iterNdx						(0)
{
}

const char* getBlendLayoutQualifier (rr::BlendEquationAdvanced equation)
{
	static const char* s_qualifiers[] =
	{
		"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",
	};
	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qualifiers) == rr::BLENDEQUATION_ADVANCED_LAST);
	DE_ASSERT(de::inBounds<int>(equation, 0, rr::BLENDEQUATION_ADVANCED_LAST));
	return s_qualifiers[equation];
}

glu::ProgramSources getBlendProgramSrc (rr::BlendEquationAdvanced equation, glu::RenderContext& renderContext)
{
	const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));

	static const char*	s_vertSrc	= "${GLSL_VERSION_DECL}\n"
									  "in highp vec4 a_position;\n"
									  "in mediump vec4 a_color;\n"
									  "out mediump vec4 v_color;\n"
									  "void main()\n"
									  "{\n"
									  "	gl_Position = a_position;\n"
									  "	v_color = a_color;\n"
									  "}\n";
	static const char*	s_fragSrc	= "${GLSL_VERSION_DECL}\n"
									  "${EXTENSION}"
									  "in mediump vec4 v_color;\n"
									  "layout(${SUPPORT_QUALIFIER}) out;\n"
									  "layout(location = 0) out mediump vec4 o_color;\n"
									  "void main()\n"
									  "{\n"
									  "	o_color = v_color;\n"
									  "}\n";

	map<string, string> args;
	args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
	args["EXTENSION"] = supportsES32 ? "\n" : "#extension GL_KHR_blend_equation_advanced : require\n";
	args["SUPPORT_QUALIFIER"] = getBlendLayoutQualifier(equation);

	return glu::ProgramSources()
		<< glu::VertexSource(tcu::StringTemplate(s_vertSrc).specialize(args))
		<< glu::FragmentSource(tcu::StringTemplate(s_fragSrc).specialize(args));
}

void AdvancedBlendCase::init (void)
{
	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
	const bool				useFbo			= m_rtType != RENDERTARGETTYPE_DEFAULT;
	const bool				useSRGB			= m_rtType == RENDERTARGETTYPE_SRGB_FBO;

	m_coherentExtensionSupported = m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced_coherent");

	if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
		if (!m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
			TCU_THROW(NotSupportedError, "GL_KHR_blend_equation_advanced is not supported");

	if (m_coherentBlending && !m_coherentExtensionSupported)
		TCU_THROW(NotSupportedError, "GL_KHR_blend_equation_advanced_coherent is not supported");

	TCU_CHECK(gl.blendBarrier);

	DE_ASSERT(!m_program);
	DE_ASSERT(!m_referenceRenderer);
	DE_ASSERT(!m_refColorBuffer);

	m_program = new glu::ShaderProgram(m_context.getRenderContext(), getBlendProgramSrc(sglr::rr_util::mapGLBlendEquationAdvanced(m_blendMode), m_context.getRenderContext()));
	m_testCtx.getLog() << *m_program;

	if (!m_program->isOk())
	{
		delete m_program;
		m_program = DE_NULL;
		TCU_FAIL("Compile failed");
	}

	m_referenceRenderer	= new ReferenceQuadRenderer;
	m_refColorBuffer	= new TextureLevel(TextureFormat(useSRGB ? TextureFormat::sRGBA : TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_viewportWidth, m_viewportHeight);

	if (useFbo)
	{
		const deUint32	format		= useSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA8;
		const int		numSamples	= m_rtType == RENDERTARGETTYPE_MSAA_FBO ? 4 : 0;

		m_testCtx.getLog() << TestLog::Message << "Using FBO of size (" << m_renderWidth << ", " << m_renderHeight << ") with format "
											   << glu::getTextureFormatStr(format) << " and " << numSamples << " samples"
						   << TestLog::EndMessage;

		gl.genRenderbuffers(1, &m_colorRbo);
		gl.bindRenderbuffer(GL_RENDERBUFFER, m_colorRbo);
		gl.renderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, format, m_renderWidth, m_renderHeight);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create color RBO");

		gl.genFramebuffers(1, &m_fbo);
		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRbo);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create FBO");

		TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

		if (numSamples > 0)
		{
			// Create resolve FBO
			gl.genRenderbuffers(1, &m_resolveColorRbo);
			gl.bindRenderbuffer(GL_RENDERBUFFER, m_resolveColorRbo);
			gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, m_renderWidth, m_renderHeight);
			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create resolve color RBO");

			gl.genFramebuffers(1, &m_resolveFbo);
			gl.bindFramebuffer(GL_FRAMEBUFFER, m_resolveFbo);
			gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_resolveColorRbo);
			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create FBO");

			TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

			gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
		}

		if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()) && useSRGB)
			gl.enable(GL_FRAMEBUFFER_SRGB);
	}
	else
		DE_ASSERT(m_rtType == RENDERTARGETTYPE_DEFAULT);

	m_iterNdx = 0;
}

AdvancedBlendCase::~AdvancedBlendCase (void)
{
	AdvancedBlendCase::deinit();
}

void AdvancedBlendCase::deinit (void)
{
	delete m_program;
	delete m_referenceRenderer;
	delete m_refColorBuffer;

	m_program			= DE_NULL;
	m_referenceRenderer	= DE_NULL;
	m_refColorBuffer	= DE_NULL;

	if (m_colorRbo || m_fbo)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();

		gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);

		if (m_colorRbo != 0)
		{
			gl.deleteRenderbuffers(1, &m_colorRbo);
			m_colorRbo = 0;
		}

		if (m_fbo != 0)
		{
			gl.deleteFramebuffers(1, &m_fbo);
			m_fbo = 0;
		}

		if (m_resolveColorRbo)
		{
			gl.deleteRenderbuffers(1, &m_resolveColorRbo);
			m_resolveColorRbo = 0;
		}

		if (m_resolveFbo)
		{
			gl.deleteRenderbuffers(1, &m_resolveFbo);
			m_resolveFbo = 0;
		}

		if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()) && RENDERTARGETTYPE_SRGB_FBO == m_rtType)
			gl.disable(GL_FRAMEBUFFER_SRGB);
	}
}

static tcu::Vec4 randomColor (de::Random* rnd)
{
	const float rgbValues[]		= { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f };
	const float alphaValues[]	= { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f };

	// \note Spec assumes premultiplied inputs.
	const float a = rnd->choose<float>(DE_ARRAY_BEGIN(alphaValues), DE_ARRAY_END(alphaValues));
	const float r = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues));
	const float g = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues));
	const float b = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues));
	return tcu::Vec4(r, g, b, a);
}

static tcu::ConstPixelBufferAccess getLinearAccess (const tcu::ConstPixelBufferAccess& access)
{
	if (access.getFormat().order == TextureFormat::sRGBA)
		return tcu::ConstPixelBufferAccess(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8),
										   access.getWidth(), access.getHeight(), access.getDepth(),
										   access.getRowPitch(), access.getSlicePitch(), access.getDataPtr());
	else
		return access;
}

AdvancedBlendCase::IterateResult AdvancedBlendCase::iterate (void)
{
	const glu::RenderContext&		renderCtx		= m_context.getRenderContext();
	const glw::Functions&			gl				= renderCtx.getFunctions();
	de::Random						rnd				(deStringHash(getName()) ^ deInt32Hash(m_iterNdx));
	const int						viewportX		= rnd.getInt(0, m_renderWidth - m_viewportWidth);
	const int						viewportY		= rnd.getInt(0, m_renderHeight - m_viewportHeight);
	const bool						useFbo			= m_rtType != RENDERTARGETTYPE_DEFAULT;
	const bool						requiresResolve	= m_rtType == RENDERTARGETTYPE_MSAA_FBO;
	const int						numQuads		= m_overdrawCount+1;
	TextureLevel					renderedImg		(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_viewportWidth, m_viewportHeight);
	vector<Vec4>					colors			(numQuads*4);

	for (vector<Vec4>::iterator col = colors.begin(); col != colors.end(); ++col)
		*col = randomColor(&rnd);

	// Render with GL.
	{
		const deUint32		program				= m_program->getProgram();
		const int			posLoc				= gl.getAttribLocation(program, "a_position");
		const int			colorLoc			= gl.getAttribLocation(program, "a_color");
		deUint32			vao					= 0;
		const glu::Buffer	indexBuffer			(renderCtx);
		const glu::Buffer	positionBuffer		(renderCtx);
		const glu::Buffer	colorBuffer			(renderCtx);
		vector<Vec2>		positions			(numQuads*4);
		vector<deUint16>	indices				(numQuads*6);
		const deUint16		singleQuadIndices[]	= { 0, 2, 1, 1, 2, 3 };
		const Vec2			singleQuadPos[]		=
		{
			Vec2(-1.0f, -1.0f),
			Vec2(-1.0f, +1.0f),
			Vec2(+1.0f, -1.0f),
			Vec2(+1.0f, +1.0f),
		};

		TCU_CHECK(posLoc >= 0 && colorLoc >= 0);

		for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
		{
			std::copy(DE_ARRAY_BEGIN(singleQuadPos), DE_ARRAY_END(singleQuadPos), &positions[quadNdx*4]);
			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(singleQuadIndices); ndx++)
				indices[quadNdx*6 + ndx] = (deUint16)(quadNdx*4 + singleQuadIndices[ndx]);
		}

		if (!glu::isContextTypeES(renderCtx.getType()))
		{
			gl.genVertexArrays(1, &vao);
			gl.bindVertexArray(vao);
		}

		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *indexBuffer);
		gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(indices.size()*sizeof(indices[0])), &indices[0], GL_STATIC_DRAW);

		gl.bindBuffer(GL_ARRAY_BUFFER, *positionBuffer);
		gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(positions.size()*sizeof(positions[0])), &positions[0], GL_STATIC_DRAW);
		gl.enableVertexAttribArray(posLoc);
		gl.vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL);

		gl.bindBuffer(GL_ARRAY_BUFFER, *colorBuffer);
		gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(colors.size()*sizeof(colors[0])), &colors[0], GL_STATIC_DRAW);
		gl.enableVertexAttribArray(colorLoc);
		gl.vertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffers");

		gl.useProgram(program);
		gl.viewport(viewportX, viewportY, m_viewportWidth, m_viewportHeight);
		gl.blendEquation(m_blendMode);

		// \note coherent extension enables GL_BLEND_ADVANCED_COHERENT_KHR by default
		if (m_coherentBlending)
			gl.enable(GL_BLEND_ADVANCED_COHERENT_KHR);
		else if (m_coherentExtensionSupported)
			gl.disable(GL_BLEND_ADVANCED_COHERENT_KHR);

		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set render state");

		gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

		gl.disable(GL_BLEND);
		gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL);
		gl.enable(GL_BLEND);

		if (!m_coherentBlending)
			gl.blendBarrier();

		if (m_coherentBlending)
		{
			gl.drawElements(GL_TRIANGLES, 6*(numQuads-1), GL_UNSIGNED_SHORT, (const void*)(deUintptr)(6*sizeof(deUint16)));
		}
		else
		{
			for (int quadNdx = 1; quadNdx < numQuads; quadNdx++)
			{
				gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void*)(deUintptr)(quadNdx*6*sizeof(deUint16)));
				gl.blendBarrier();
			}
		}

		if (vao)
			gl.deleteVertexArrays(1, &vao);

		gl.flush();
		GLU_EXPECT_NO_ERROR(gl.getError(), "Render failed");
	}

	// Render reference.
	{
		rr::FragmentOperationState		referenceState;
		const tcu::PixelBufferAccess	colorAccess		= gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess());
		const tcu::PixelBufferAccess	nullAccess		= tcu::PixelBufferAccess();
		IntegerQuad						quad;

		if (!useFbo && m_context.getRenderTarget().getPixelFormat().alphaBits == 0)
		{
			// Emulate lack of alpha by clearing to 1 and masking out alpha writes
			tcu::clear(*m_refColorBuffer, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
			referenceState.colorMask = tcu::BVec4(true, true, true, false);
		}

		referenceState.blendEquationAdvaced	= sglr::rr_util::mapGLBlendEquationAdvanced(m_blendMode);

		quad.posA = tcu::IVec2(0, 0);
		quad.posB = tcu::IVec2(m_viewportWidth-1, m_viewportHeight-1);

		for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
		{
			referenceState.blendMode = quadNdx == 0 ? rr::BLENDMODE_NONE : rr::BLENDMODE_ADVANCED;
			std::copy(&colors[4*quadNdx], &colors[4*quadNdx] + 4, &quad.color[0]);
			m_referenceRenderer->render(colorAccess, nullAccess /* no depth */, nullAccess /* no stencil */, quad, referenceState);
		}
	}

	if (requiresResolve)
	{
		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolveFbo);
		gl.blitFramebuffer(0, 0, m_renderWidth, m_renderHeight, 0, 0, m_renderWidth, m_renderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Resolve blit failed");

		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_resolveFbo);
	}

	glu::readPixels(renderCtx, viewportX, viewportY, renderedImg.getAccess());
	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");

	if (requiresResolve)
		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);

	{
		const bool	isHSLMode	= m_blendMode == GL_HSL_HUE			||
								  m_blendMode == GL_HSL_SATURATION	||
								  m_blendMode == GL_HSL_COLOR		||
								  m_blendMode == GL_HSL_LUMINOSITY;
		bool		comparePass	= false;

		if (isHSLMode)
		{
			// Compensate for more demanding HSL code by using fuzzy comparison.
			const float threshold = 0.002f;
			comparePass = tcu::fuzzyCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result",
											getLinearAccess(m_refColorBuffer->getAccess()),
											renderedImg.getAccess(),
											threshold, tcu::COMPARE_LOG_RESULT);
		}
		else
		{
			const UVec4 compareThreshold = (useFbo ? tcu::PixelFormat(8, 8, 8, 8) : m_context.getRenderTarget().getPixelFormat()).getColorThreshold().toIVec().asUint()
									 * UVec4(5) / UVec4(2) + UVec4(3 * m_overdrawCount);

			comparePass = tcu::bilinearCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result",
											  getLinearAccess(m_refColorBuffer->getAccess()),
											  renderedImg.getAccess(),
											  tcu::RGBA(compareThreshold[0], compareThreshold[1], compareThreshold[2], compareThreshold[3]),
											  tcu::COMPARE_LOG_RESULT);
		}

		if (!comparePass)
		{
			m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
			return STOP;
		}
	}

	m_iterNdx += 1;

	if (m_iterNdx < m_numIters)
		return CONTINUE;
	else
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
		return STOP;
	}
}

class BlendAdvancedCoherentStateCase : public TestCase
{
public:
											BlendAdvancedCoherentStateCase	(Context&						context,
																			 const char*					name,
																			 const char*					description,
																			 gls::StateQueryUtil::QueryType	type);
private:
	IterateResult							iterate							(void);

	const gls::StateQueryUtil::QueryType	m_type;
};

BlendAdvancedCoherentStateCase::BlendAdvancedCoherentStateCase	(Context&						context,
																 const char*					name,
																 const char*					description,
																 gls::StateQueryUtil::QueryType	type)
	: TestCase	(context, name, description)
	, m_type	(type)
{
}

BlendAdvancedCoherentStateCase::IterateResult BlendAdvancedCoherentStateCase::iterate (void)
{
	TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced_coherent"), "GL_KHR_blend_equation_advanced_coherent is not supported");

	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");

	gl.enableLogging(true);

	// check inital value
	{
		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
		gls::StateQueryUtil::verifyStateBoolean(result, gl, GL_BLEND_ADVANCED_COHERENT_KHR, true, m_type);
	}

	// check toggle
	{
		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Toggle", "Toggle");
		gl.glDisable(GL_BLEND_ADVANCED_COHERENT_KHR);
		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glDisable");

		gls::StateQueryUtil::verifyStateBoolean(result, gl, GL_BLEND_ADVANCED_COHERENT_KHR, false, m_type);

		gl.glEnable(GL_BLEND_ADVANCED_COHERENT_KHR);
		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glEnable");

		gls::StateQueryUtil::verifyStateBoolean(result, gl, GL_BLEND_ADVANCED_COHERENT_KHR, true, m_type);
	}

	result.setTestContextResult(m_testCtx);
	return STOP;
}

class BlendEquationStateCase : public TestCase
{
public:
											BlendEquationStateCase	(Context&						context,
																	 const char*					name,
																	 const char*					description,
																	 const glw::GLenum*				equations,
																	 int							numEquations,
																	 gls::StateQueryUtil::QueryType	type);
private:
	IterateResult							iterate					(void);

	const gls::StateQueryUtil::QueryType	m_type;
	const glw::GLenum*						m_equations;
	const int								m_numEquations;
};

BlendEquationStateCase::BlendEquationStateCase	(Context&						context,
												 const char*					name,
												 const char*					description,
												 const glw::GLenum*				equations,
												 int							numEquations,
												 gls::StateQueryUtil::QueryType	type)
	: TestCase			(context, name, description)
	, m_type			(type)
	, m_equations		(equations)
	, m_numEquations	(numEquations)
{
}

BlendEquationStateCase::IterateResult BlendEquationStateCase::iterate (void)
{
	if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)))
		TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"), "GL_KHR_blend_equation_advanced is not supported");

	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");

	gl.enableLogging(true);

	for (int ndx = 0; ndx < m_numEquations; ++ndx)
	{
		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Type", "Test " + de::toString(glu::getBlendEquationStr(m_equations[ndx])));

		gl.glBlendEquation(m_equations[ndx]);
		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glBlendEquation");

		gls::StateQueryUtil::verifyStateInteger(result, gl, GL_BLEND_EQUATION, m_equations[ndx], m_type);
	}

	result.setTestContextResult(m_testCtx);
	return STOP;
}

class BlendEquationIndexedStateCase : public TestCase
{
public:
											BlendEquationIndexedStateCase	(Context&						context,
																			 const char*					name,
																			 const char*					description,
																			 const glw::GLenum*				equations,
																			 int							numEquations,
																			 gls::StateQueryUtil::QueryType	type);
private:
	IterateResult							iterate							(void);

	const gls::StateQueryUtil::QueryType	m_type;
	const glw::GLenum*						m_equations;
	const int								m_numEquations;
};

BlendEquationIndexedStateCase::BlendEquationIndexedStateCase	(Context&						context,
																 const char*					name,
																 const char*					description,
																 const glw::GLenum*				equations,
																 int							numEquations,
																 gls::StateQueryUtil::QueryType	type)
	: TestCase			(context, name, description)
	, m_type			(type)
	, m_equations		(equations)
	, m_numEquations	(numEquations)
{
}

BlendEquationIndexedStateCase::IterateResult BlendEquationIndexedStateCase::iterate (void)
{
	const auto& renderContext = m_context.getRenderContext();
	if (!glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)) &&
		!glu::contextSupports(renderContext.getType(), glu::ApiType::core(4, 5)))
	{
		TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"), "GL_KHR_blend_equation_advanced is not supported");
		TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"), "GL_EXT_draw_buffers_indexed is not supported");
	}

	glu::CallLogWrapper		gl		(renderContext.getFunctions(), m_testCtx.getLog());
	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");

	gl.enableLogging(true);

	for (int ndx = 0; ndx < m_numEquations; ++ndx)
	{
		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Type", "Test " + de::toString(glu::getBlendEquationStr(m_equations[ndx])));

		gl.glBlendEquationi(2, m_equations[ndx]);
		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glBlendEquationi");

		gls::StateQueryUtil::verifyStateIndexedInteger(result, gl, GL_BLEND_EQUATION, 2, m_equations[ndx], m_type);
	}

	result.setTestContextResult(m_testCtx);
	return STOP;
}

} // anonymous

AdvancedBlendTests::AdvancedBlendTests (Context& context)
	: TestCaseGroup(context, "blend_equation_advanced", "GL_blend_equation_advanced Tests")
{
}

AdvancedBlendTests::~AdvancedBlendTests (void)
{
}

void AdvancedBlendTests::init (void)
{
	static const glw::GLenum s_blendEquations[] =
	{
		GL_MULTIPLY,
		GL_SCREEN,
		GL_OVERLAY,
		GL_DARKEN,
		GL_LIGHTEN,
		GL_COLORDODGE,
		GL_COLORBURN,
		GL_HARDLIGHT,
		GL_SOFTLIGHT,
		GL_DIFFERENCE,
		GL_EXCLUSION,
		GL_HSL_HUE,
		GL_HSL_SATURATION,
		GL_HSL_COLOR,
		GL_HSL_LUMINOSITY,

	};

	tcu::TestCaseGroup* const	stateQueryGroup		= new tcu::TestCaseGroup(m_testCtx, "state_query",		"State query tests");
	tcu::TestCaseGroup* const	basicGroup			= new tcu::TestCaseGroup(m_testCtx, "basic",			"Single quad only");
	tcu::TestCaseGroup* const	srgbGroup			= new tcu::TestCaseGroup(m_testCtx, "srgb",				"Advanced blending with sRGB FBO");
	tcu::TestCaseGroup* const	msaaGroup			= new tcu::TestCaseGroup(m_testCtx, "msaa",				"Advanced blending with MSAA FBO");
	tcu::TestCaseGroup* const	barrierGroup		= new tcu::TestCaseGroup(m_testCtx, "barrier",			"Multiple overlapping quads with blend barriers");
	tcu::TestCaseGroup* const	coherentGroup		= new tcu::TestCaseGroup(m_testCtx, "coherent",			"Overlapping quads with coherent blending");
	tcu::TestCaseGroup* const	coherentMsaaGroup	= new tcu::TestCaseGroup(m_testCtx, "coherent_msaa",	"Overlapping quads with coherent blending with MSAA FBO");

	addChild(stateQueryGroup);
	addChild(basicGroup);
	addChild(srgbGroup);
	addChild(msaaGroup);
	addChild(barrierGroup);
	addChild(coherentGroup);
	addChild(coherentMsaaGroup);

	// .state_query
	{
		using namespace gls::StateQueryUtil;

		stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_getboolean",	"Test BLEND_ADVANCED_COHERENT_KHR", QUERY_BOOLEAN));
		stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_isenabled",	"Test BLEND_ADVANCED_COHERENT_KHR", QUERY_ISENABLED));
		stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_getinteger",	"Test BLEND_ADVANCED_COHERENT_KHR", QUERY_INTEGER));
		stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_getinteger64",	"Test BLEND_ADVANCED_COHERENT_KHR", QUERY_INTEGER64));
		stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_getfloat",		"Test BLEND_ADVANCED_COHERENT_KHR", QUERY_FLOAT));

		stateQueryGroup->addChild(new BlendEquationStateCase(m_context, "blend_equation_getboolean",	"Test BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_BOOLEAN));
		stateQueryGroup->addChild(new BlendEquationStateCase(m_context, "blend_equation_getinteger",	"Test BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INTEGER));
		stateQueryGroup->addChild(new BlendEquationStateCase(m_context, "blend_equation_getinteger64",	"Test BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INTEGER64));
		stateQueryGroup->addChild(new BlendEquationStateCase(m_context, "blend_equation_getfloat",		"Test BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_FLOAT));

		stateQueryGroup->addChild(new BlendEquationIndexedStateCase(m_context, "blend_equation_getbooleani_v",		"Test per-attchment BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INDEXED_BOOLEAN));
		stateQueryGroup->addChild(new BlendEquationIndexedStateCase(m_context, "blend_equation_getintegeri_v",		"Test per-attchment BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INDEXED_INTEGER));
		stateQueryGroup->addChild(new BlendEquationIndexedStateCase(m_context, "blend_equation_getinteger64i_v",	"Test per-attchment BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INDEXED_INTEGER64));
	}

	// others
	for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(s_blendEquations); modeNdx++)
	{
		const char* const		name		= getEquationName(s_blendEquations[modeNdx]);
		const char* const		desc		= "";
		const deUint32			mode		= s_blendEquations[modeNdx];

		basicGroup->addChild		(new AdvancedBlendCase(m_context, name, desc, mode, 1, false,	RENDERTARGETTYPE_DEFAULT));
		srgbGroup->addChild			(new AdvancedBlendCase(m_context, name, desc, mode, 1, false,	RENDERTARGETTYPE_SRGB_FBO));
		msaaGroup->addChild			(new AdvancedBlendCase(m_context, name, desc, mode, 1, false,	RENDERTARGETTYPE_MSAA_FBO));
		barrierGroup->addChild		(new AdvancedBlendCase(m_context, name, desc, mode, 4, false,	RENDERTARGETTYPE_DEFAULT));
		coherentGroup->addChild		(new AdvancedBlendCase(m_context, name, desc, mode, 4, true,	RENDERTARGETTYPE_DEFAULT));
		coherentMsaaGroup->addChild	(new AdvancedBlendCase(m_context, name, desc, mode, 4, true,	RENDERTARGETTYPE_MSAA_FBO));
	}
}

} // Functional
} // gles31
} // deqp
