/*-------------------------------------------------------------------------
 * 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;
};

static bool checkES32orGL45Support(Context& ctx)
{
	auto ctxType = ctx.getRenderContext().getType();
	return contextSupports(ctxType, glu::ApiType::es(3, 2)) ||
		   contextSupports(ctxType, glu::ApiType::core(4, 5));
}

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 supportsES32orGL45 = checkES32orGL45Support(m_context);

	if (!supportsES32orGL45)
	{
		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 supportsES32orGL45 = checkES32orGL45Support(context);

	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 (supportsES32orGL45)
		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 supportsES32orGL45 = checkES32orGL45Support(m_context);

	if (!supportsES32orGL45 && !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 supportsES32orGL45 = checkES32orGL45Support(m_context);

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