/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2015 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 Indexed blend operation tests (GL_EXT_draw_buffers_indexed)
 *//*--------------------------------------------------------------------*/

#include "es31fDrawBuffersIndexedTests.hpp"

#include "gluContextInfo.hpp"
#include "gluDrawUtil.hpp"
#include "gluObjectWrapper.hpp"
#include "gluPixelTransfer.hpp"
#include "gluShaderProgram.hpp"
#include "gluStrUtil.hpp"
#include "gluTextureUtil.hpp"

#include "sglrReferenceUtils.hpp"

#include "rrMultisamplePixelBufferAccess.hpp"
#include "rrRenderer.hpp"

#include "glwEnums.hpp"
#include "glwFunctions.hpp"

#include "tcuEither.hpp"
#include "tcuImageCompare.hpp"
#include "tcuMaybe.hpp"
#include "tcuResultCollector.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuTestLog.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVector.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuFloat.hpp"

#include "deRandom.hpp"
#include "deArrayUtil.hpp"
#include "deStringUtil.hpp"
#include "deUniquePtr.hpp"

#include "deInt32.h"

#include <string>
#include <vector>
#include <map>

using tcu::BVec4;
using tcu::Either;
using tcu::IVec2;
using tcu::IVec4;
using tcu::Maybe;
using tcu::TestLog;
using tcu::TextureFormat;
using tcu::TextureLevel;
using tcu::UVec4;
using tcu::Vec2;
using tcu::Vec4;
using tcu::just;

using std::string;
using std::vector;
using std::map;

using sglr::rr_util::mapGLBlendEquation;
using sglr::rr_util::mapGLBlendFunc;
using sglr::rr_util::mapGLBlendEquationAdvanced;

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace
{

typedef deUint32 BlendEq;

bool isAdvancedBlendEq (BlendEq eq)
{
	switch (eq)
	{
		case GL_MULTIPLY:		return true;
		case GL_SCREEN:			return true;
		case GL_OVERLAY:		return true;
		case GL_DARKEN:			return true;
		case GL_LIGHTEN:		return true;
		case GL_COLORDODGE:		return true;
		case GL_COLORBURN:		return true;
		case GL_HARDLIGHT:		return true;
		case GL_SOFTLIGHT:		return true;
		case GL_DIFFERENCE:		return true;
		case GL_EXCLUSION:		return true;
		case GL_HSL_HUE:		return true;
		case GL_HSL_SATURATION:	return true;
		case GL_HSL_COLOR:		return true;
		case GL_HSL_LUMINOSITY:	return true;
		default:
			return false;
	}
}

struct SeparateBlendEq
{
	SeparateBlendEq (BlendEq rgb_, BlendEq alpha_)
		: rgb	(rgb_)
		, alpha	(alpha_)
	{
	}

	BlendEq rgb;
	BlendEq alpha;
};

struct BlendFunc
{
	BlendFunc (deUint32 src_, deUint32 dst_)
		: src (src_)
		, dst (dst_)
	{
	}

	deUint32 src;
	deUint32 dst;
};

struct SeparateBlendFunc
{
	SeparateBlendFunc (BlendFunc rgb_, BlendFunc alpha_)
		: rgb	(rgb_)
		, alpha	(alpha_)
	{
	}

	BlendFunc rgb;
	BlendFunc alpha;
};

typedef deUint32 DrawBuffer;

struct BlendState
{
	BlendState (void) {}

	BlendState (const Maybe<bool>&									enableBlend_,
				const Maybe<Either<BlendEq, SeparateBlendEq> >&		blendEq_,
				const Maybe<Either<BlendFunc, SeparateBlendFunc> >&	blendFunc_,
				const Maybe<BVec4>&									colorMask_)
		: enableBlend	(enableBlend_)
		, blendEq		(blendEq_)
		, blendFunc		(blendFunc_)
		, colorMask		(colorMask_)
	{
	}

	bool isEmpty (void) const
	{
		return (!enableBlend) && (!blendEq) && (!blendFunc) && (!colorMask);
	}

	Maybe<bool>										enableBlend;
	Maybe<Either<BlendEq, SeparateBlendEq> >		blendEq;
	Maybe<Either<BlendFunc, SeparateBlendFunc> >	blendFunc;
	Maybe<BVec4>									colorMask;
};

void setCommonBlendState (const glw::Functions& gl, const BlendState& blend)
{
	if (blend.enableBlend)
	{
		if (*blend.enableBlend)
			gl.enable(GL_BLEND);
		else
			gl.disable(GL_BLEND);
	}

	if (blend.colorMask)
	{
		const BVec4& mask = *blend.colorMask;

		gl.colorMask(mask.x(), mask.y(), mask.z(), mask.w());
	}

	if (blend.blendEq)
	{
		const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;

		if (blendEq.is<BlendEq>())
			gl.blendEquation(blendEq.get<BlendEq>());
		else if (blendEq.is<SeparateBlendEq>())
			gl.blendEquationSeparate(blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
		else
			DE_ASSERT(false);
	}

	if (blend.blendFunc)
	{
		const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;

		if (blendFunc.is<BlendFunc>())
			gl.blendFunc(blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
		else if (blendFunc.is<SeparateBlendFunc>())
			gl.blendFuncSeparate(blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
		else
			DE_ASSERT(false);
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set common blend state.");
}

void setIndexedBlendState (const glw::Functions& gl, const BlendState& blend, deUint32 index)
{
	if (blend.enableBlend)
	{
		if (*blend.enableBlend)
			gl.enablei(GL_BLEND, index);
		else
			gl.disablei(GL_BLEND, index);
	}

	if (blend.colorMask)
	{
		const BVec4 mask = *blend.colorMask;

		gl.colorMaski(index, mask.x(), mask.y(), mask.z(), mask.w());
	}

	if (blend.blendEq)
	{
		const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;

		if (blendEq.is<BlendEq>())
			gl.blendEquationi(index, blendEq.get<BlendEq>());
		else if (blendEq.is<SeparateBlendEq>())
			gl.blendEquationSeparatei(index, blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
		else
			DE_ASSERT(false);
	}

	if (blend.blendFunc)
	{
		const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;

		if (blendFunc.is<BlendFunc>())
			gl.blendFunci(index, blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
		else if (blendFunc.is<SeparateBlendFunc>())
			gl.blendFuncSeparatei(index, blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
		else
			DE_ASSERT(false);
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set draw buffer specifig blend state.");
}

class DrawBufferInfo
{
public:
							DrawBufferInfo	(bool					render,
											 const IVec2&			size,
											 const BlendState&		blendState,
											 const TextureFormat&	format);

	const TextureFormat&	getFormat		(void) const { return m_format;		}
	const IVec2&			getSize			(void) const { return m_size;		}
	const BlendState&		getBlendState	(void) const { return m_blendState;	}
	bool					getRender		(void) const { return m_render;		}

private:
	bool					m_render;
	IVec2					m_size;
	TextureFormat			m_format;
	BlendState				m_blendState;
};

DrawBufferInfo::DrawBufferInfo (bool render, const IVec2& size, const BlendState& blendState, const TextureFormat& format)
	: m_render		(render)
	, m_size		(size)
	, m_format		(format)
	, m_blendState	(blendState)
{
}

void clearRenderbuffer (const glw::Functions&			gl,
						const tcu::TextureFormat&		format,
						int								renderbufferNdx,
						int								renderbufferCount,
						tcu::TextureLevel&				refRenderbuffer)
{
	const tcu::TextureFormatInfo	info		= tcu::getTextureFormatInfo(format);

	// Clear each buffer to different color
	const float						redScale	= float(renderbufferNdx + 1) / float(renderbufferCount);
	const float						blueScale	= float(renderbufferCount - renderbufferNdx) / float(renderbufferCount);
	const float						greenScale	= float(((renderbufferCount/2) + renderbufferNdx) % renderbufferCount) / float(renderbufferCount);
	// Alpha should never be zero as advanced blend equations assume premultiplied alpha.
	const float						alphaScale	= float(1 + (((renderbufferCount/2) + renderbufferCount - renderbufferNdx) % renderbufferCount)) / float(renderbufferCount);

	switch (tcu::getTextureChannelClass(format.type))
	{
		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
		{
			const float red		= -1000.0f + 2000.0f * redScale;
			const float green	= -1000.0f + 2000.0f * greenScale;
			const float blue	= -1000.0f + 2000.0f * blueScale;
			const float alpha	= -1000.0f + 2000.0f * alphaScale;
			const Vec4	color	(red, green, blue, alpha);

			tcu::clear(refRenderbuffer, color);
			gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
			break;
		}

		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
		{
			const deInt32	red		= deInt32(info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale);
			const deInt32	green	= deInt32(info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale);
			const deInt32	blue	= deInt32(info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale);
			const deInt32	alpha	= deInt32(info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale);
			const IVec4		color	(red, green, blue, alpha);

			tcu::clear(refRenderbuffer, color);
			gl.clearBufferiv(GL_COLOR, renderbufferNdx, color.getPtr());
			break;
		}

		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
		{
			const deUint32	red		= deUint32(info.valueMax.x() * redScale);
			const deUint32	green	= deUint32(info.valueMax.y() * greenScale);
			const deUint32	blue	= deUint32(info.valueMax.z() * blueScale);
			const deUint32	alpha	= deUint32(info.valueMax.w() * alphaScale);
			const UVec4		color	(red, green, blue, alpha);

			tcu::clear(refRenderbuffer, color);
			gl.clearBufferuiv(GL_COLOR, renderbufferNdx, color.getPtr());
			break;
		}

		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
		{
			const float red		= info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale;
			const float green	= info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale;
			const float blue	= info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale;
			const float alpha	= info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale;
			const Vec4	color	(red, green, blue, alpha);

			tcu::clear(refRenderbuffer, color);
			gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
			break;
		}

		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
		{
			const float red		= info.valueMax.x() * redScale;
			const float green	= info.valueMax.y() * greenScale;
			const float blue	= info.valueMax.z() * blueScale;
			const float alpha	= info.valueMax.w() * alphaScale;
			const Vec4	color	(red, green, blue, alpha);

			tcu::clear(refRenderbuffer, color);
			gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
			break;
		}

		default:
			DE_ASSERT(DE_FALSE);
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear renderbuffer.");
}

void genRenderbuffers (const glw::Functions&			gl,
						const vector<DrawBufferInfo>&	drawBuffers,
						const glu::Framebuffer&			framebuffer,
						const glu::RenderbufferVector&	renderbuffers,
						vector<TextureLevel>&			refRenderbuffers)
{
	vector<deUint32> bufs;

	bufs.resize(drawBuffers.size());

	DE_ASSERT(drawBuffers.size() == renderbuffers.size());
	DE_ASSERT(drawBuffers.size() == refRenderbuffers.size());

	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);

	for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
	{
		const DrawBufferInfo&		drawBuffer	= drawBuffers[renderbufferNdx];
		const TextureFormat&		format		= drawBuffer.getFormat();
		const IVec2&				size		= drawBuffer.getSize();
		const deUint32				glFormat	= glu::getInternalFormat(format);

		bufs[renderbufferNdx]					= GL_COLOR_ATTACHMENT0 + renderbufferNdx;
		refRenderbuffers[renderbufferNdx]		= TextureLevel(drawBuffer.getFormat(), size.x(), size.y());

		gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
		gl.renderbufferStorage(GL_RENDERBUFFER, glFormat, size.x(), size.y());
		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + renderbufferNdx, GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create renderbuffer.");
	}

	gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));

	for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
	{
		const DrawBufferInfo&		drawBuffer	= drawBuffers[renderbufferNdx];
		const TextureFormat&		format		= drawBuffer.getFormat();

		clearRenderbuffer(gl, format, renderbufferNdx, (int)refRenderbuffers.size(),  refRenderbuffers[renderbufferNdx]);
	}

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

Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
{
	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);

	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);

	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);

	const tcu::IVec4	srcBits		= tcu::getTextureFormatBitDepth(sourceFormat);
	const tcu::IVec4	readBits	= tcu::getTextureFormatBitDepth(readPixelsFormat);

	return Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>();
}

UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
{
	const tcu::IVec4	srcMantissaBits		= tcu::getTextureFormatMantissaBitDepth(sourceFormat);
	const tcu::IVec4	readMantissaBits	= tcu::getTextureFormatMantissaBitDepth(readPixelsFormat);
	tcu::IVec4			ULPDiff(0);

	for (int i = 0; i < 4; i++)
		if (readMantissaBits[i] >= srcMantissaBits[i])
			ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i];

	return UVec4(4) * (UVec4(1) << (ULPDiff.cast<deUint32>()));
}

void verifyRenderbuffer (TestLog&					log,
						 tcu::ResultCollector&		results,
						 const tcu::TextureFormat&	format,
						 int						renderbufferNdx,
						 const tcu::TextureLevel&	refRenderbuffer,
						 const tcu::TextureLevel&	result)
{
	switch (tcu::getTextureChannelClass(format.type))
	{
		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
		{
			const string	name		= "Renderbuffer" + de::toString(renderbufferNdx);
			const string	desc		= "Compare renderbuffer " + de::toString(renderbufferNdx);
			const UVec4		threshold	= getFloatULPThreshold(format, result.getFormat());

			if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
				results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");

			break;
		}

		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
		{
			const string	name		= "Renderbuffer" + de::toString(renderbufferNdx);
			const string	desc		= "Compare renderbuffer " + de::toString(renderbufferNdx);
			const UVec4		threshold	(1, 1, 1, 1);

			if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
				results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");

			break;
		}

		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
		{
			const string	name		= "Renderbuffer" + de::toString(renderbufferNdx);
			const string	desc		= "Compare renderbuffer " + de::toString(renderbufferNdx);
			const Vec4		threshold	= getFixedPointFormatThreshold(format, result.getFormat());

			if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
				results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");

			break;
		}

		default:
			DE_ASSERT(DE_FALSE);
	}
}

TextureFormat getReadPixelFormat (const TextureFormat& format)
{
	switch (tcu::getTextureChannelClass(format.type))
	{
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
			return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32);

		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
			return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32);

		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
			return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);

		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
			return TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT);

		default:
			DE_ASSERT(false);
			return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
	}
}

void verifyRenderbuffers (TestLog&							log,
							tcu::ResultCollector&				results,
							glu::RenderContext&				renderContext,
							const glu::RenderbufferVector&	renderbuffers,
							const glu::Framebuffer&			framebuffer,
							const vector<TextureLevel>&		refRenderbuffers)
{
	const glw::Functions& gl = renderContext.getFunctions();

	DE_ASSERT(renderbuffers.size() == refRenderbuffers.size());

	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);

	for (int renderbufferNdx = 0; renderbufferNdx < (int)renderbuffers.size(); renderbufferNdx++)
	{
		const TextureLevel&	refRenderbuffer	= refRenderbuffers[renderbufferNdx];
		const int			width			= refRenderbuffer.getWidth();
		const int			height			= refRenderbuffer.getHeight();
		const TextureFormat	format			= refRenderbuffer.getFormat();

		tcu::TextureLevel	result			(getReadPixelFormat(format), width, height);

		gl.readBuffer(GL_COLOR_ATTACHMENT0 + renderbufferNdx);
		glu::readPixels(renderContext, 0, 0, result.getAccess());
		GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels from renderbuffer failed.");

		verifyRenderbuffer(log, results, format, renderbufferNdx, refRenderbuffer, result);
	}

	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
}

static const float s_quadCoords[] =
{
	-0.5f, -0.5f,
	 0.5f, -0.5f,
	 0.5f,  0.5f,

	 0.5f,  0.5f,
	-0.5f,  0.5f,
	-0.5f, -0.5f
};

void setBlendState (rr::FragmentOperationState& fragOps, const BlendState& state)
{
	if (state.blendEq)
	{
		if (state.blendEq->is<BlendEq>())
		{
			if (isAdvancedBlendEq(state.blendEq->get<BlendEq>()))
			{
				const rr::BlendEquationAdvanced	equation = mapGLBlendEquationAdvanced(state.blendEq->get<BlendEq>());

				fragOps.blendMode				= rr::BLENDMODE_ADVANCED;
				fragOps.blendEquationAdvaced	= equation;
			}
			else
			{
				const rr::BlendEquation equation = mapGLBlendEquation(state.blendEq->get<BlendEq>());

				fragOps.blendMode				= rr::BLENDMODE_STANDARD;
				fragOps.blendRGBState.equation	= equation;
				fragOps.blendAState.equation	= equation;
			}
		}
		else
		{
			DE_ASSERT(state.blendEq->is<SeparateBlendEq>());

			fragOps.blendMode				= rr::BLENDMODE_STANDARD;
			fragOps.blendRGBState.equation	= mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().rgb);
			fragOps.blendAState.equation	= mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().alpha);
		}
	}

	if (state.blendFunc)
	{
		if (state.blendFunc->is<BlendFunc>())
		{
			const rr::BlendFunc srcFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().src);
			const rr::BlendFunc dstFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().dst);

			fragOps.blendRGBState.srcFunc	= srcFunction;
			fragOps.blendRGBState.dstFunc	= dstFunction;

			fragOps.blendAState.srcFunc		= srcFunction;
			fragOps.blendAState.dstFunc		= dstFunction;
		}
		else
		{
			DE_ASSERT(state.blendFunc->is<SeparateBlendFunc>());

			fragOps.blendRGBState.srcFunc	= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.src);
			fragOps.blendRGBState.dstFunc	= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.dst);

			fragOps.blendAState.srcFunc		= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.src);
			fragOps.blendAState.dstFunc		= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.dst);
		}
	}

	if (state.colorMask)
		fragOps.colorMask = *state.colorMask;
}

rr::RenderState createRenderState (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const DrawBufferInfo& info, int subpixelBits)
{
	const IVec2		size	= info.getSize();
	rr::RenderState	state	(rr::ViewportState(rr::WindowRectangle(0, 0, size.x(), size.y())), subpixelBits);

	state.fragOps.blendMode = rr::BLENDMODE_STANDARD;

	setBlendState(state.fragOps, preCommonBlendState);
	setBlendState(state.fragOps, info.getBlendState());
	setBlendState(state.fragOps, postCommonBlendState);

	if (postCommonBlendState.enableBlend)
		state.fragOps.blendMode = (*(postCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
	else  if (info.getBlendState().enableBlend)
		state.fragOps.blendMode = (*(info.getBlendState().enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
	else if (preCommonBlendState.enableBlend)
		state.fragOps.blendMode = (*(preCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
	else
		state.fragOps.blendMode = rr::BLENDMODE_NONE;

	if (tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
		&& tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
		&& tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
		state.fragOps.blendMode = rr::BLENDMODE_NONE;

	return state;
}

class VertexShader : public rr::VertexShader
{
public:
					VertexShader	(void);
	virtual void	shadeVertices	(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
};

VertexShader::VertexShader (void)
	: rr::VertexShader	(1, 1)
{
	m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
	m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
}

void VertexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
{
	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
	{
		rr::VertexPacket& packet = *packets[packetNdx];

		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
		packet.outputs[0]	= 0.5f * (Vec4(1.0f) + rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx));
	}
}

class FragmentShader : public rr::FragmentShader
{
public:
			FragmentShader	(int drawBufferNdx, const DrawBufferInfo& info);
	void	shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;

private:
	const int				m_drawBufferNdx;
	const DrawBufferInfo	m_info;
};

FragmentShader::FragmentShader (int drawBufferNdx, const DrawBufferInfo& info)
	: rr::FragmentShader	(1, 1)
	, m_drawBufferNdx		(drawBufferNdx)
	, m_info				(info)
{
	m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;

	switch (tcu::getTextureChannelClass(m_info.getFormat().type))
	{
		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
			m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
			break;

		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
			m_outputs[0].type = rr::GENERICVECTYPE_UINT32;
			break;

		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
			m_outputs[0].type = rr::GENERICVECTYPE_INT32;
			break;

		default:
			DE_ASSERT(false);
	};
}

void FragmentShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
{
	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
	{
		rr::FragmentPacket& packet = packets[packetNdx];

		DE_ASSERT(m_drawBufferNdx >= 0);
		DE_UNREF(m_info);

		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
		{
			const Vec2	vColor		= rr::readVarying<float>(packet, context, 0, fragNdx).xy();
			const float	values[]	=
			{
				vColor.x(),
				vColor.y(),
				(1.0f - vColor.x()),
				(1.0f - vColor.y())
			};

			switch (tcu::getTextureChannelClass(m_info.getFormat().type))
			{
				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
				{
					const Vec4 color (values[(m_drawBufferNdx + 0) % 4],
									  values[(m_drawBufferNdx + 1) % 4],
									  values[(m_drawBufferNdx + 2) % 4],
									  values[(m_drawBufferNdx + 3) % 4]);

					rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
					break;
				}

				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
				{
					const UVec4 color ((deUint32)(values[(m_drawBufferNdx + 0) % 4]),
									   (deUint32)(values[(m_drawBufferNdx + 1) % 4]),
									   (deUint32)(values[(m_drawBufferNdx + 2) % 4]),
									   (deUint32)(values[(m_drawBufferNdx + 3) % 4]));

					rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
					break;
				}

				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
				{
					const IVec4 color ((deInt32)(values[(m_drawBufferNdx + 0) % 4]),
									   (deInt32)(values[(m_drawBufferNdx + 1) % 4]),
									   (deInt32)(values[(m_drawBufferNdx + 2) % 4]),
									   (deInt32)(values[(m_drawBufferNdx + 3) % 4]));

					rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
					break;
				}

				default:
					DE_ASSERT(DE_FALSE);
			};
		}
	}
}

rr::VertexAttrib createVertexAttrib (const float* coords)
{
	rr::VertexAttrib attrib;

	attrib.type		= rr::VERTEXATTRIBTYPE_FLOAT;
	attrib.size		= 2;
	attrib.pointer	= coords;

	return attrib;
}

void renderRefQuad (const BlendState&				preCommonBlendState,
					const BlendState&				postCommonBlendState,
					const vector<DrawBufferInfo>&	drawBuffers,
					const int						subpixelBits,
					vector<TextureLevel>&			refRenderbuffers)
{
	const rr::Renderer			renderer;
	const rr::PrimitiveList		primitives		(rr::PRIMITIVETYPE_TRIANGLES, 6, 0);
	const rr::VertexAttrib		vertexAttribs[] =
	{
		createVertexAttrib(s_quadCoords)
	};

	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
	{
		if (drawBuffers[drawBufferNdx].getRender())
		{
			const rr::RenderState	renderState		(createRenderState(preCommonBlendState, postCommonBlendState, drawBuffers[drawBufferNdx], subpixelBits));
			const rr::RenderTarget	renderTarget	(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refRenderbuffers[drawBufferNdx].getAccess()));
			const VertexShader		vertexShader;
			const FragmentShader	fragmentShader	(drawBufferNdx, drawBuffers[drawBufferNdx]);
			const rr::Program		program			(&vertexShader, &fragmentShader);
			const rr::DrawCommand	command			(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, primitives);

			renderer.draw(command);
		}
	}
}

bool requiresAdvancedBlendEq (const BlendState& pre, const BlendState post, const vector<DrawBufferInfo>& drawBuffers)
{
	bool requiresAdvancedBlendEq = false;

	if (pre.blendEq && pre.blendEq->is<BlendEq>())
		requiresAdvancedBlendEq |= isAdvancedBlendEq(pre.blendEq->get<BlendEq>());

	if (post.blendEq && post.blendEq->is<BlendEq>())
		requiresAdvancedBlendEq |= isAdvancedBlendEq(post.blendEq->get<BlendEq>());

	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
	{
		const BlendState& drawBufferBlendState = drawBuffers[drawBufferNdx].getBlendState();

		if (drawBufferBlendState.blendEq && drawBufferBlendState.blendEq->is<BlendEq>())
			requiresAdvancedBlendEq |= isAdvancedBlendEq(drawBufferBlendState.blendEq->get<BlendEq>());
	}

	return requiresAdvancedBlendEq;
}

glu::VertexSource genVertexSource (glu::RenderContext& renderContext)
{
	const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));

	const char* const vertexSource =
		"${GLSL_VERSION_DECL}\n"
		"layout(location=0) in highp vec2 i_coord;\n"
		"out highp vec2 v_color;\n"
		"void main (void)\n"
		"{\n"
		"\tv_color = 0.5 * (vec2(1.0) + i_coord);\n"
		"\tgl_Position = vec4(i_coord, 0.0, 1.0);\n"
		"}";

	map<string, string> args;
	args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);

	return glu::VertexSource(tcu::StringTemplate(vertexSource).specialize(args));
}

glu::FragmentSource genFragmentSource (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
{
	std::ostringstream stream;
	const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));

	stream << "${GLSL_VERSION_DECL}\n";

	if (requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers))
	{
		stream << "${GLSL_EXTENSION}"
			   <<  "layout(blend_support_all_equations) out;\n";
	}

	stream << "in highp vec2 v_color;\n";

	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
	{
		const DrawBufferInfo&	drawBuffer			= drawBuffers[drawBufferNdx];
		const TextureFormat&	format				= drawBuffer.getFormat();

		stream << "layout(location=" << drawBufferNdx << ") out highp ";

		switch (tcu::getTextureChannelClass(format.type))
		{
			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
				stream << "vec4";
				break;

			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
				stream << "uvec4";
				break;

			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
				stream << "ivec4";
				break;

			default:
				DE_ASSERT(DE_FALSE);
		};

		stream << " o_drawBuffer" <<  drawBufferNdx << ";\n";
	}

	stream << "void main (void)\n"
		   << "{\n";

	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
	{
		const DrawBufferInfo&	drawBuffer		= drawBuffers[drawBufferNdx];
		const TextureFormat&	format			= drawBuffer.getFormat();
		const char* const		values[]		=
		{
			"v_color.x",
			"v_color.y",
			"(1.0 - v_color.x)",
			"(1.0 - v_color.y)"
		};

		stream << "\to_drawBuffer" <<  drawBufferNdx;

		switch (tcu::getTextureChannelClass(format.type))
		{
			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
				stream << " = vec4(" << values[(drawBufferNdx + 0) % 4]
					   << ", " << values[(drawBufferNdx + 1) % 4]
					   << ", " << values[(drawBufferNdx + 2) % 4]
					   << ", " << values[(drawBufferNdx + 3) % 4] << ");\n";
				break;

			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
				stream << " = uvec4(uint(" << values[(drawBufferNdx + 0) % 4]
					   << "), uint(" << values[(drawBufferNdx + 1) % 4]
					   << "), uint(" << values[(drawBufferNdx + 2) % 4]
					   << "), uint(" << values[(drawBufferNdx + 3) % 4] << "));\n";
				break;

			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
				stream << " = ivec4(int(" << values[(drawBufferNdx + 0) % 4]
					   << "), int(" << values[(drawBufferNdx + 1) % 4]
					   << "), int(" << values[(drawBufferNdx + 2) % 4]
					   << "), int(" << values[(drawBufferNdx + 3) % 4] << "));\n";
				break;

			default:
				DE_ASSERT(DE_FALSE);
		};
	}

	stream << "}";

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

	return glu::FragmentSource(tcu::StringTemplate(stream.str()).specialize(args));
}

glu::ProgramSources genShaderSources (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
{
	return glu::ProgramSources() << genVertexSource(renderContext) << genFragmentSource(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext);
}

void renderGLQuad (glu::RenderContext&			renderContext,
				   const glu::ShaderProgram&	program)
{
	const glu::VertexArrayBinding vertexArrays[] =
	{
		glu::VertexArrayBinding(glu::BindingPoint(0), glu::VertexArrayPointer(glu::VTX_COMP_FLOAT, glu::VTX_COMP_CONVERT_NONE, 2, 6, 0, s_quadCoords))
	};

	glu::draw(renderContext, program.getProgram(), 1, vertexArrays, glu::pr::Triangles(6));
}

void renderQuad (TestLog&						log,
				 glu::RenderContext&			renderContext,
				 const BlendState&				preCommonBlendState,
				 const BlendState&				postCommonBlendState,
				 const vector<DrawBufferInfo>&	drawBuffers,
				 const glu::Framebuffer&		framebuffer,
				 vector<TextureLevel>&			refRenderbuffers)
{
	const glw::Functions&		gl						= renderContext.getFunctions();
	const glu::ShaderProgram	program					(gl, genShaderSources(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext));
	const IVec2					size					= drawBuffers[0].getSize();
	const bool					requiresBlendBarriers	= requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers);

	vector<deUint32> bufs;

	bufs.resize(drawBuffers.size());

	for (int bufNdx = 0; bufNdx < (int)bufs.size(); bufNdx++)
		bufs[bufNdx] = (drawBuffers[bufNdx].getRender() ? GL_COLOR_ATTACHMENT0 + bufNdx : GL_NONE);

	log << program;

	gl.viewport(0, 0, size.x(), size.y());
	gl.useProgram(program.getProgram());
	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);

	setCommonBlendState(gl, preCommonBlendState);

	for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
		setIndexedBlendState(gl, drawBuffers[renderbufferNdx].getBlendState(), renderbufferNdx);

	setCommonBlendState(gl, postCommonBlendState);

	gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));

	if (requiresBlendBarriers)
		gl.blendBarrier();

	renderGLQuad(renderContext, program);

	if (requiresBlendBarriers)
		gl.blendBarrier();

	gl.drawBuffers(0, 0);
	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
	gl.useProgram(0);

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

	int subpixelBits = 0;
	gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);

	renderRefQuad(preCommonBlendState, postCommonBlendState, drawBuffers, subpixelBits, refRenderbuffers);
}

void logBlendState (TestLog&			log,
					const BlendState&	blend)
{
	if (blend.enableBlend)
	{
		if (*blend.enableBlend)
			log << TestLog::Message << "Enable blending." << TestLog::EndMessage;
		else
			log << TestLog::Message << "Disable blending." << TestLog::EndMessage;
	}

	if (blend.colorMask)
	{
		const BVec4 mask = *blend.colorMask;

		log << TestLog::Message << "Set color mask: " << mask << "." << TestLog::EndMessage;
	}

	if (blend.blendEq)
	{
		const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;

		if (blendEq.is<BlendEq>())
			log << TestLog::Message << "Set blend equation: " << glu::getBlendEquationStr(blendEq.get<BlendEq>()) << "." << TestLog::EndMessage;
		else if (blendEq.is<SeparateBlendEq>())
			log << TestLog::Message << "Set blend equation rgb: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().rgb) << ", alpha: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().alpha) << "." << TestLog::EndMessage;
		else
			DE_ASSERT(false);
	}

	if (blend.blendFunc)
	{
		const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;

		if (blendFunc.is<BlendFunc>())
			log << TestLog::Message << "Set blend function source: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().dst) << "." << TestLog::EndMessage;
		else if (blendFunc.is<SeparateBlendFunc>())
		{
			log << TestLog::Message << "Set blend function rgb source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.dst) << "." << TestLog::EndMessage;
			log << TestLog::Message << "Set blend function alpha source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.dst) << "." << TestLog::EndMessage;
		}
		else
			DE_ASSERT(false);
	}
}

void logTestCaseInfo (TestLog&						log,
					  const BlendState&				preCommonBlendState,
					  const BlendState&				postCommonBlendState,
					  const vector<DrawBufferInfo>&	drawBuffers)
{
	{
		tcu::ScopedLogSection drawBuffersSection(log, "DrawBuffers", "Draw buffers");

		for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
		{
			const tcu::ScopedLogSection	drawBufferSection	(log, "DrawBuffer" + de::toString(drawBufferNdx), "Draw Buffer " + de::toString(drawBufferNdx));
			const DrawBufferInfo&		drawBuffer			= drawBuffers[drawBufferNdx];

			log << TestLog::Message << "Format: " << drawBuffer.getFormat() << TestLog::EndMessage;
			log << TestLog::Message << "Size: " << drawBuffer.getSize() << TestLog::EndMessage;
			log << TestLog::Message << "Render: " << (drawBuffer.getRender() ? "true" : "false") << TestLog::EndMessage;
		}
	}

	if (!preCommonBlendState.isEmpty())
	{
		tcu::ScopedLogSection s(log, "PreCommonState", "First set common blend state");
		logBlendState(log, preCommonBlendState);
	}

	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
	{
		if (!drawBuffers[drawBufferNdx].getBlendState().isEmpty())
		{
			const tcu::ScopedLogSection s(log, "DrawBufferState" + de::toString(drawBufferNdx), "Set DrawBuffer " + de::toString(drawBufferNdx) + " state to");

			logBlendState(log, drawBuffers[drawBufferNdx].getBlendState());
		}
	}

	if (!postCommonBlendState.isEmpty())
	{
		tcu::ScopedLogSection s(log, "PostCommonState", "After set common blend state");
		logBlendState(log, postCommonBlendState);
	}
}

void runTest (TestLog&						log,
			  tcu::ResultCollector&			results,
			  glu::RenderContext&			renderContext,

			  const BlendState&				preCommonBlendState,
			  const BlendState&				postCommonBlendState,
			  const vector<DrawBufferInfo>&	drawBuffers)
{
	const glw::Functions&	gl					= renderContext.getFunctions();
	glu::RenderbufferVector	renderbuffers		(gl, drawBuffers.size());
	glu::Framebuffer		framebuffer			(gl);
	vector<TextureLevel>	refRenderbuffers	(drawBuffers.size());

	logTestCaseInfo(log, preCommonBlendState, postCommonBlendState, drawBuffers);

	genRenderbuffers(gl, drawBuffers, framebuffer, renderbuffers, refRenderbuffers);

	renderQuad(log, renderContext, preCommonBlendState, postCommonBlendState, drawBuffers, framebuffer, refRenderbuffers);

	verifyRenderbuffers(log, results, renderContext, renderbuffers, framebuffer, refRenderbuffers);
}

class DrawBuffersIndexedTest : public TestCase
{
public:
					DrawBuffersIndexedTest (Context&						context,
											const BlendState&				preCommonBlendState,
											const BlendState&				postCommonBlendState,
											const vector<DrawBufferInfo>&	drawBuffers,
											const string&					name,
											const string&					description);

	void			init					(void);
	IterateResult	iterate					(void);

private:
	const BlendState				m_preCommonBlendState;
	const BlendState				m_postCommonBlendState;
	const vector<DrawBufferInfo>	m_drawBuffers;
};

DrawBuffersIndexedTest::DrawBuffersIndexedTest (Context&						context,
												const BlendState&				preCommonBlendState,
												const BlendState&				postCommonBlendState,
												const vector<DrawBufferInfo>&	drawBuffers,
												const string&					name,
												const string&					description)
	: TestCase					(context, name.c_str(), description.c_str())
	, m_preCommonBlendState		(preCommonBlendState)
	, m_postCommonBlendState	(postCommonBlendState)
	, m_drawBuffers				(drawBuffers)
{
}

void DrawBuffersIndexedTest::init (void)
{
	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));

	if (!supportsES32)
	{
		if (requiresAdvancedBlendEq(m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers) && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
			TCU_THROW(NotSupportedError, "Extension GL_KHR_blend_equation_advanced not supported");

		if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
			TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
	}
}

TestCase::IterateResult DrawBuffersIndexedTest::iterate (void)
{
	TestLog&				log		= m_testCtx.getLog();
	tcu::ResultCollector	results	(log);

	runTest(log, results, m_context.getRenderContext(), m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers);

	results.setTestContextResult(m_testCtx);

	return STOP;
}

BlendEq getRandomBlendEq (de::Random& rng)
{
	const BlendEq eqs[] =
	{
		GL_FUNC_ADD,
		GL_FUNC_SUBTRACT,
		GL_FUNC_REVERSE_SUBTRACT,
		GL_MIN,
		GL_MAX
	};

	return de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(eqs)>(eqs, rng.getUint32() % DE_LENGTH_OF_ARRAY(eqs));
}

BlendFunc getRandomBlendFunc (de::Random& rng)
{
	const deUint32 funcs[] =
	{
		GL_ZERO,
		GL_ONE,
		GL_SRC_COLOR,
		GL_ONE_MINUS_SRC_COLOR,
		GL_DST_COLOR,
		GL_ONE_MINUS_DST_COLOR,
		GL_SRC_ALPHA,
		GL_ONE_MINUS_SRC_ALPHA,
		GL_DST_ALPHA,
		GL_ONE_MINUS_DST_ALPHA,
		GL_CONSTANT_COLOR,
		GL_ONE_MINUS_CONSTANT_COLOR,
		GL_CONSTANT_ALPHA,
		GL_ONE_MINUS_CONSTANT_ALPHA,
		GL_SRC_ALPHA_SATURATE
	};

	const deUint32 src = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
	const deUint32 dst = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));

	return BlendFunc(src, dst);
}

void genRandomBlendState (de::Random& rng, BlendState& blendState)
{
	if (rng.getBool())
		blendState.enableBlend = rng.getBool();

	if (rng.getBool())
	{
		if (rng.getBool())
			blendState.blendEq = getRandomBlendEq(rng);
		else
		{
			const BlendEq	rgb		= getRandomBlendEq(rng);
			const BlendEq	alpha	= getRandomBlendEq(rng);

			blendState.blendEq		= SeparateBlendEq(rgb, alpha);
		}
	}

	if (rng.getBool())
	{
		if (rng.getBool())
			blendState.blendFunc = getRandomBlendFunc(rng);
		else
		{
			const BlendFunc	rgb		= getRandomBlendFunc(rng);
			const BlendFunc	alpha	= getRandomBlendFunc(rng);

			blendState.blendFunc	= SeparateBlendFunc(rgb, alpha);
		}
	}

	if (rng.getBool())
	{
		const bool red		= rng.getBool();
		const bool green	= rng.getBool();
		const bool blue		= rng.getBool();
		const bool alpha	= rng.getBool();

		blendState.colorMask = BVec4(red, blue, green, alpha);
	}
}

TextureFormat getRandomFormat (de::Random& rng, Context& context)
{
	const bool supportsES32 = glu::contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2));

	const deUint32 glFormats[] =
	{
		GL_R8,
		GL_RG8,
		GL_RGB8,
		GL_RGB565,
		GL_RGBA4,
		GL_RGB5_A1,
		GL_RGBA8,
		GL_RGB10_A2,
		GL_RGB10_A2UI,
		GL_R8I,
		GL_R8UI,
		GL_R16I,
		GL_R16UI,
		GL_R32I,
		GL_R32UI,
		GL_RG8I,
		GL_RG8UI,
		GL_RG16I,
		GL_RG16UI,
		GL_RG32I,
		GL_RG32UI,
		GL_RGBA8I,
		GL_RGBA8UI,
		GL_RGBA16I,
		GL_RGBA16UI,
		GL_RGBA32I,
		GL_RGBA32UI,
		GL_RGBA16F,
		GL_R32F,
		GL_RG32F,
		GL_RGBA32F,
		GL_R11F_G11F_B10F
	};

	if (supportsES32)
		return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % DE_LENGTH_OF_ARRAY(glFormats)));
	else
	{
		DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(glFormats) == 32);
		return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % (DE_LENGTH_OF_ARRAY(glFormats) - 5)));
	}
}

void genRandomTest (de::Random& rng, BlendState& preCommon, BlendState& postCommon, vector<DrawBufferInfo>& drawBuffers, int maxDrawBufferCount, Context& context)
{
	genRandomBlendState(rng, preCommon);
	genRandomBlendState(rng, postCommon);

	for (int drawBufferNdx = 0; drawBufferNdx < maxDrawBufferCount; drawBufferNdx++)
	{
		const bool			render		= rng.getFloat() > 0.1f;
		const IVec2			size		(64, 64);
		const TextureFormat	format		(getRandomFormat(rng, context));
		BlendState			blendState;

		genRandomBlendState(rng, blendState);

		// 32bit float formats don't support blending in GLES32
		if (format.type == tcu::TextureFormat::FLOAT)
		{
			// If format is 32bit float post common can't enable blending
			if (postCommon.enableBlend && *postCommon.enableBlend)
			{
				// Either don't set enable blend or disable blending
				if (rng.getBool())
					postCommon.enableBlend = tcu::nothing<bool>();
				else
					postCommon.enableBlend = tcu::just(false);
			}

			// If post common doesn't disable blending, per attachment state or
			// pre common must.
			if (!postCommon.enableBlend)
			{
				// If pre common enables blend per attachment must disable it
				// If per attachment state changes blend state it must disable it
				if ((preCommon.enableBlend && *preCommon.enableBlend)
					|| blendState.enableBlend)
					blendState.enableBlend = tcu::just(false);
			}
		}

		drawBuffers.push_back(DrawBufferInfo(render, size, blendState, format));
	}
}

class MaxDrawBuffersIndexedTest : public TestCase
{
public:
					MaxDrawBuffersIndexedTest	(Context& contet, int seed);

	void			init						(void);
	IterateResult	iterate						(void);

private:
	const int		m_seed;
};

MaxDrawBuffersIndexedTest::MaxDrawBuffersIndexedTest (Context& context, int seed)
	: TestCase	(context, de::toString(seed).c_str(), de::toString(seed).c_str())
	, m_seed	(deInt32Hash(seed) ^ 1558001307u)
{
}

void MaxDrawBuffersIndexedTest::init (void)
{
	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));

	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
		TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
}

TestCase::IterateResult MaxDrawBuffersIndexedTest::iterate (void)
{
	TestLog&				log						= m_testCtx.getLog();
	tcu::ResultCollector	results					(log);
	de::Random				rng						(m_seed);
	BlendState				preCommonBlendState;
	BlendState				postCommonBlendState;
	vector<DrawBufferInfo>	drawBuffers;

	genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, 4, m_context);

	runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);

	results.setTestContextResult(m_testCtx);

	return STOP;
}

class ImplMaxDrawBuffersIndexedTest : public TestCase
{
public:
					ImplMaxDrawBuffersIndexedTest	(Context& contet, int seed);

	void			init							(void);
	IterateResult	iterate							(void);

private:
	const int		m_seed;
};

ImplMaxDrawBuffersIndexedTest::ImplMaxDrawBuffersIndexedTest (Context& context, int seed)
	: TestCase	(context, de::toString(seed).c_str(), de::toString(seed).c_str())
	, m_seed	(deInt32Hash(seed) ^ 2686315738u)
{
}

void ImplMaxDrawBuffersIndexedTest::init (void)
{
	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));

	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
		TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
}

TestCase::IterateResult ImplMaxDrawBuffersIndexedTest::iterate (void)
{
	TestLog&				log						= m_testCtx.getLog();
	tcu::ResultCollector	results					(log);
	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
	de::Random				rng						(m_seed);
	deInt32					maxDrawBuffers			= 0;
	BlendState				preCommonBlendState;
	BlendState				postCommonBlendState;
	vector<DrawBufferInfo>	drawBuffers;

	gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_DRAW_BUFFERS) failed");

	TCU_CHECK(maxDrawBuffers > 0);

	genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, maxDrawBuffers, m_context);

	runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);

	results.setTestContextResult(m_testCtx);

	return STOP;
}

enum PrePost
{
	PRE,
	POST
};

TestCase* createDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
{
	const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());

	if (prepost == PRE)
	{
		const BlendState		preState	= BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
														 commonState.blendEq,
														 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
														 tcu::nothing<BVec4>());
		vector<DrawBufferInfo>	drawBuffers;

		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));

		return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
	}
	else if (prepost == POST)
	{
		const BlendState		preState	= BlendState(just(true),
														 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
														 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
														 tcu::nothing<BVec4>());
		vector<DrawBufferInfo>	drawBuffers;

		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));

		return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
	}
	else
	{
		DE_ASSERT(false);
		return DE_NULL;
	}
}

TestCase* createAdvancedEqDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
{
	const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());

	if (prepost == PRE)
	{
		const BlendState		preState	= BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
														 commonState.blendEq,
														 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
														 tcu::nothing<BVec4>());
		vector<DrawBufferInfo>	drawBuffers;

		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));

		return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
	}
	else if (prepost == POST)
	{
		const BlendState		preState	= BlendState(just(true),
														 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
														 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
														 tcu::nothing<BVec4>());
		vector<DrawBufferInfo>	drawBuffers;

		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));

		return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
	}
	else
	{
		DE_ASSERT(false);
		return DE_NULL;
	}
}

void addDrawBufferCommonTests (TestCaseGroup* root, PrePost prepost)
{
	const BlendState		emptyState	= BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());

	{
		const BlendState	disableState	= BlendState(just(false), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
		const BlendState	enableState		= BlendState(just(true), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());

		root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_enable",	enableState,	enableState));
		root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_disable",	disableState,	disableState));
		root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_enable",	disableState,	enableState));
		root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_disable",	enableState,	disableState));
	}

	{
		const BlendState	eqStateA			= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_ADD), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
		const BlendState	eqStateB			= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_SUBTRACT), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());

		const BlendState	separateEqStateA	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_ADD, GL_FUNC_SUBTRACT)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
		const BlendState	separateEqStateB	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_SUBTRACT, GL_FUNC_ADD)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());

		const BlendState	advancedEqStateA	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_DIFFERENCE), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
		const BlendState	advancedEqStateB	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_SCREEN), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());

		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_blend_eq", eqStateA, eqStateB));
		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_separate_blend_eq", eqStateA, separateEqStateB));
		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_advanced_blend_eq", eqStateA, advancedEqStateB));

		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_blend_eq", separateEqStateA, eqStateB));
		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_separate_blend_eq", separateEqStateA, separateEqStateB));
		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_advanced_blend_eq", separateEqStateA, advancedEqStateB));

		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_blend_eq", advancedEqStateA, eqStateB));
		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_separate_blend_eq", advancedEqStateA, separateEqStateB));
		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_advanced_blend_eq", advancedEqStateA, advancedEqStateB));
	}

	{
		const BlendState	funcStateA			= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA)), Maybe<BVec4>());
		const BlendState	funcStateB			= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA)), Maybe<BVec4>());
		const BlendState	separateFuncStateA	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA), BlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA))), Maybe<BVec4>());
		const BlendState	separateFuncStateB	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA), BlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA))), Maybe<BVec4>());

		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_blend_func",					funcStateA,			funcStateB));
		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_separate_blend_func",			funcStateA,			separateFuncStateB));
		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_blend_func",			separateFuncStateA,	funcStateB));
		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_separate_blend_func",	separateFuncStateA,	separateFuncStateB));
	}

	{
		const BlendState	commonColorMaskState	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(true, false, true, false)));
		const BlendState	bufferColorMaskState	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(false, true, false, true)));

		root->addChild(createDiffTest(root->getContext(), prepost, "common_color_mask_buffer_color_mask", commonColorMaskState, bufferColorMaskState));
	}
}

void addRandomMaxTest (TestCaseGroup* root)
{
	for (int i = 0; i < 20; i++)
		root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i));
}

void addRandomImplMaxTest (TestCaseGroup* root)
{
	for (int i = 0; i < 20; i++)
		root->addChild(new ImplMaxDrawBuffersIndexedTest(root->getContext(), i));
}

} // anonymous

TestCaseGroup* createDrawBuffersIndexedTests (Context& context)
{
	const BlendState		emptyState		= BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
	TestCaseGroup* const	group			= new TestCaseGroup(context, "draw_buffers_indexed", "Test for indexed draw buffers. GL_EXT_draw_buffers_indexed.");

	TestCaseGroup* const	preGroup		= new TestCaseGroup(context, "overwrite_common", "Set common state and overwrite it with draw buffer blend state.");
	TestCaseGroup* const	postGroup		= new TestCaseGroup(context, "overwrite_indexed", "Set indexed blend state and overwrite it with common state.");
	TestCaseGroup* const	randomGroup		= new TestCaseGroup(context, "random", "Random indexed blend state tests.");
	TestCaseGroup* const	maxGroup		= new TestCaseGroup(context, "max_required_draw_buffers", "Random tests using minimum maximum number of draw buffers.");
	TestCaseGroup* const	maxImplGroup	= new TestCaseGroup(context, "max_implementation_draw_buffers", "Random tests using maximum number of draw buffers reported by implementation.");

	group->addChild(preGroup);
	group->addChild(postGroup);
	group->addChild(randomGroup);

	randomGroup->addChild(maxGroup);
	randomGroup->addChild(maxImplGroup);

	addDrawBufferCommonTests(preGroup, PRE);
	addDrawBufferCommonTests(postGroup, POST);
	addRandomMaxTest(maxGroup);
	addRandomImplMaxTest(maxImplGroup);

	return group;
}

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