/*-------------------------------------------------------------------------
 * 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)
{
	const IVec2		size	= info.getSize();
	rr::RenderState	state	(rr::ViewportState(rr::WindowRectangle(0, 0, size.x(), size.y())));

	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,
					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]));
			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 isES32 = 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"] = isES32 ? 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 isES32 = 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"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
	args["GLSL_EXTENSION"] = isES32 ? "\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");

	renderRefQuad(preCommonBlendState, postCommonBlendState, drawBuffers, 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 isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));

	if (!isES32)
	{
		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 isES32 = 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 (isES32)
		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 isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));

	if (!isES32 && !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 isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));

	if (!isES32 && !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
