/*-------------------------------------------------------------------------
 * 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;
				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, tcu::Nothing, tcu::Nothing, tcu::Nothing);

	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);
		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,
														 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
														 tcu::Nothing);
		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, tcu::Nothing, tcu::Nothing, tcu::Nothing);

	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);
		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,
														 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
														 tcu::Nothing);
		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, Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_ADD), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
		const BlendState	eqStateB			= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_SUBTRACT), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());

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

		const BlendState	advancedEqStateA	= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(GL_DIFFERENCE), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
		const BlendState	advancedEqStateB	= BlendState(tcu::Nothing, 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, Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA)), Maybe<BVec4>());
		const BlendState	funcStateB			= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA)), Maybe<BVec4>());
		const BlendState	separateFuncStateA	= BlendState(tcu::Nothing, 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, 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, Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(true, false, true, false)));
		const BlendState	bufferColorMaskState	= BlendState(tcu::Nothing, 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
