/*-------------------------------------------------------------------------
 * 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_KHR:		return "multiply";
		case GL_SCREEN_KHR:			return "screen";
		case GL_OVERLAY_KHR:		return "overlay";
		case GL_DARKEN_KHR:			return "darken";
		case GL_LIGHTEN_KHR:		return "lighten";
		case GL_COLORDODGE_KHR:		return "colordodge";
		case GL_COLORBURN_KHR:		return "colorburn";
		case GL_HARDLIGHT_KHR:		return "hardlight";
		case GL_SOFTLIGHT_KHR:		return "softlight";
		case GL_DIFFERENCE_KHR:		return "difference";
		case GL_EXCLUSION_KHR:		return "exclusion";
		case GL_HSL_HUE_KHR:		return "hsl_hue";
		case GL_HSL_SATURATION_KHR:	return "hsl_saturation";
		case GL_HSL_COLOR_KHR:		return "hsl_color";
		case GL_HSL_LUMINOSITY_KHR:	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_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)
{
	static const char*	s_vertSrc	= "#version 310 es\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	= "#version 310 es\n"
									  "#extension GL_KHR_blend_equation_advanced : require\n"
									  "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["SUPPORT_QUALIFIER"] = getBlendLayoutQualifier(equation);

	return glu::ProgramSources()
		<< glu::VertexSource(s_vertSrc)
		<< 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;

	if (!m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
		throw tcu::NotSupportedError("GL_KHR_blend_equation_advanced is not supported", DE_NULL, __FILE__, __LINE__);

	if (m_coherentBlending && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced_coherent"))
		throw tcu::NotSupportedError("GL_KHR_blend_equation_advanced_coherent is not supported", DE_NULL, __FILE__, __LINE__);

	TCU_CHECK(gl.blendBarrierKHR);

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

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

	m_program = new glu::ShaderProgram(m_context.getRenderContext(), getBlendProgramSrc(sglr::rr_util::mapGLBlendEquationAdvanced(m_blendMode)));
	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::getPixelFormatStr(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);
		}
	}
	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;
		}
	}
}

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");
		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]);
		}

		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.blendBarrierKHR();

		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.blendBarrierKHR();
			}
		}

		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		(TextureFormat(), 0, 0, 0, DE_NULL);
		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_KHR			||
								  m_blendMode == GL_HSL_SATURATION_KHR	||
								  m_blendMode == GL_HSL_COLOR_KHR		||
								  m_blendMode == GL_HSL_LUMINOSITY_KHR;
		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)
{
	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)
{
	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		(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.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_KHR_blend_equation_advanced Tests")
{
}

AdvancedBlendTests::~AdvancedBlendTests (void)
{
}

void AdvancedBlendTests::init (void)
{
	static const glw::GLenum s_blendEquations[] =
	{
		GL_MULTIPLY_KHR,
		GL_SCREEN_KHR,
		GL_OVERLAY_KHR,
		GL_DARKEN_KHR,
		GL_LIGHTEN_KHR,
		GL_COLORDODGE_KHR,
		GL_COLORBURN_KHR,
		GL_HARDLIGHT_KHR,
		GL_SOFTLIGHT_KHR,
		GL_DIFFERENCE_KHR,
		GL_EXCLUSION_KHR,
		GL_HSL_HUE_KHR,
		GL_HSL_SATURATION_KHR,
		GL_HSL_COLOR_KHR,
		GL_HSL_LUMINOSITY_KHR,
	};

	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
