Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2015 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Indexed blend operation tests (GL_EXT_draw_buffers_indexed)
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fDrawBuffersIndexedTests.hpp"
     25 
     26 #include "gluContextInfo.hpp"
     27 #include "gluDrawUtil.hpp"
     28 #include "gluObjectWrapper.hpp"
     29 #include "gluPixelTransfer.hpp"
     30 #include "gluShaderProgram.hpp"
     31 #include "gluStrUtil.hpp"
     32 #include "gluTextureUtil.hpp"
     33 
     34 #include "sglrReferenceUtils.hpp"
     35 
     36 #include "rrMultisamplePixelBufferAccess.hpp"
     37 #include "rrRenderer.hpp"
     38 
     39 #include "glwEnums.hpp"
     40 #include "glwFunctions.hpp"
     41 
     42 #include "tcuEither.hpp"
     43 #include "tcuImageCompare.hpp"
     44 #include "tcuMaybe.hpp"
     45 #include "tcuResultCollector.hpp"
     46 #include "tcuTestLog.hpp"
     47 #include "tcuTexture.hpp"
     48 #include "tcuTextureUtil.hpp"
     49 #include "tcuVector.hpp"
     50 #include "tcuVectorUtil.hpp"
     51 
     52 #include "deRandom.hpp"
     53 #include "deArrayUtil.hpp"
     54 #include "deStringUtil.hpp"
     55 #include "deUniquePtr.hpp"
     56 
     57 #include "deInt32.h"
     58 
     59 #include <string>
     60 #include <vector>
     61 
     62 using tcu::BVec4;
     63 using tcu::Either;
     64 using tcu::IVec2;
     65 using tcu::IVec4;
     66 using tcu::Maybe;
     67 using tcu::TestLog;
     68 using tcu::TextureFormat;
     69 using tcu::TextureLevel;
     70 using tcu::UVec4;
     71 using tcu::Vec2;
     72 using tcu::Vec4;
     73 using tcu::just;
     74 
     75 using std::string;
     76 using std::vector;
     77 
     78 using sglr::rr_util::mapGLBlendEquation;
     79 using sglr::rr_util::mapGLBlendFunc;
     80 using sglr::rr_util::mapGLBlendEquationAdvanced;
     81 
     82 namespace deqp
     83 {
     84 namespace gles31
     85 {
     86 namespace Functional
     87 {
     88 namespace
     89 {
     90 
     91 typedef deUint32 BlendEq;
     92 
     93 bool isAdvancedBlendEq (BlendEq eq)
     94 {
     95 	switch (eq)
     96 	{
     97 		case GL_MULTIPLY_KHR:		return true;
     98 		case GL_SCREEN_KHR:			return true;
     99 		case GL_OVERLAY_KHR:		return true;
    100 		case GL_DARKEN_KHR:			return true;
    101 		case GL_LIGHTEN_KHR:		return true;
    102 		case GL_COLORDODGE_KHR:		return true;
    103 		case GL_COLORBURN_KHR:		return true;
    104 		case GL_HARDLIGHT_KHR:		return true;
    105 		case GL_SOFTLIGHT_KHR:		return true;
    106 		case GL_DIFFERENCE_KHR:		return true;
    107 		case GL_EXCLUSION_KHR:		return true;
    108 		case GL_HSL_HUE_KHR:		return true;
    109 		case GL_HSL_SATURATION_KHR:	return true;
    110 		case GL_HSL_COLOR_KHR:		return true;
    111 		case GL_HSL_LUMINOSITY_KHR:	return true;
    112 		default:
    113 			return false;
    114 	}
    115 }
    116 
    117 struct SeparateBlendEq
    118 {
    119 	SeparateBlendEq (BlendEq rgb_, BlendEq alpha_)
    120 		: rgb	(rgb_)
    121 		, alpha	(alpha_)
    122 	{
    123 	}
    124 
    125 	BlendEq rgb;
    126 	BlendEq alpha;
    127 };
    128 
    129 struct BlendFunc
    130 {
    131 	BlendFunc (deUint32 src_, deUint32 dst_)
    132 		: src (src_)
    133 		, dst (dst_)
    134 	{
    135 	}
    136 
    137 	deUint32 src;
    138 	deUint32 dst;
    139 };
    140 
    141 struct SeparateBlendFunc
    142 {
    143 	SeparateBlendFunc (BlendFunc rgb_, BlendFunc alpha_)
    144 		: rgb	(rgb_)
    145 		, alpha	(alpha_)
    146 	{
    147 	}
    148 
    149 	BlendFunc rgb;
    150 	BlendFunc alpha;
    151 };
    152 
    153 typedef deUint32 DrawBuffer;
    154 
    155 struct BlendState
    156 {
    157 	BlendState (void) {}
    158 
    159 	BlendState (const Maybe<bool>&									enableBlend_,
    160 				const Maybe<Either<BlendEq, SeparateBlendEq> >&		blendEq_,
    161 				const Maybe<Either<BlendFunc, SeparateBlendFunc> >&	blendFunc_,
    162 				const Maybe<BVec4>&									colorMask_)
    163 		: enableBlend	(enableBlend_)
    164 		, blendEq		(blendEq_)
    165 		, blendFunc		(blendFunc_)
    166 		, colorMask		(colorMask_)
    167 	{
    168 	}
    169 
    170 	bool isEmpty (void) const
    171 	{
    172 		return (!enableBlend) && (!blendEq) && (!blendFunc) && (!colorMask);
    173 	}
    174 
    175 	Maybe<bool>										enableBlend;
    176 	Maybe<Either<BlendEq, SeparateBlendEq> >		blendEq;
    177 	Maybe<Either<BlendFunc, SeparateBlendFunc> >	blendFunc;
    178 	Maybe<BVec4>									colorMask;
    179 };
    180 
    181 void setCommonBlendState (const glw::Functions& gl, const BlendState& blend)
    182 {
    183 	if (blend.enableBlend)
    184 	{
    185 		if (*blend.enableBlend)
    186 			gl.enable(GL_BLEND);
    187 		else
    188 			gl.disable(GL_BLEND);
    189 	}
    190 
    191 	if (blend.colorMask)
    192 	{
    193 		const BVec4& mask = *blend.colorMask;
    194 
    195 		gl.colorMask(mask.x(), mask.y(), mask.z(), mask.w());
    196 	}
    197 
    198 	if (blend.blendEq)
    199 	{
    200 		const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
    201 
    202 		if (blendEq.is<BlendEq>())
    203 			gl.blendEquation(blendEq.get<BlendEq>());
    204 		else if (blendEq.is<SeparateBlendEq>())
    205 			gl.blendEquationSeparate(blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
    206 		else
    207 			DE_ASSERT(false);
    208 	}
    209 
    210 	if (blend.blendFunc)
    211 	{
    212 		const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
    213 
    214 		if (blendFunc.is<BlendFunc>())
    215 			gl.blendFunc(blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
    216 		else if (blendFunc.is<SeparateBlendFunc>())
    217 			gl.blendFuncSeparate(blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
    218 		else
    219 			DE_ASSERT(false);
    220 	}
    221 
    222 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set common blend state.");
    223 }
    224 
    225 void setIndexedBlendState (const glw::Functions& gl, const BlendState& blend, deUint32 index)
    226 {
    227 	if (blend.enableBlend)
    228 	{
    229 		if (*blend.enableBlend)
    230 			gl.enablei(GL_BLEND, index);
    231 		else
    232 			gl.disablei(GL_BLEND, index);
    233 	}
    234 
    235 	if (blend.colorMask)
    236 	{
    237 		const BVec4 mask = *blend.colorMask;
    238 
    239 		gl.colorMaski(index, mask.x(), mask.y(), mask.z(), mask.w());
    240 	}
    241 
    242 	if (blend.blendEq)
    243 	{
    244 		const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
    245 
    246 		if (blendEq.is<BlendEq>())
    247 			gl.blendEquationi(index, blendEq.get<BlendEq>());
    248 		else if (blendEq.is<SeparateBlendEq>())
    249 			gl.blendEquationSeparatei(index, blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha);
    250 		else
    251 			DE_ASSERT(false);
    252 	}
    253 
    254 	if (blend.blendFunc)
    255 	{
    256 		const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
    257 
    258 		if (blendFunc.is<BlendFunc>())
    259 			gl.blendFunci(index, blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst);
    260 		else if (blendFunc.is<SeparateBlendFunc>())
    261 			gl.blendFuncSeparatei(index, blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst);
    262 		else
    263 			DE_ASSERT(false);
    264 	}
    265 
    266 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set draw buffer specifig blend state.");
    267 }
    268 
    269 class DrawBufferInfo
    270 {
    271 public:
    272 							DrawBufferInfo	(bool					render,
    273 											 const IVec2&			size,
    274 											 const BlendState&		blendState,
    275 											 const TextureFormat&	format);
    276 
    277 	const TextureFormat&	getFormat		(void) const { return m_format;		}
    278 	const IVec2&			getSize			(void) const { return m_size;		}
    279 	const BlendState&		getBlendState	(void) const { return m_blendState;	}
    280 	bool					getRender		(void) const { return m_render;		}
    281 
    282 private:
    283 	bool					m_render;
    284 	IVec2					m_size;
    285 	TextureFormat			m_format;
    286 	BlendState				m_blendState;
    287 };
    288 
    289 DrawBufferInfo::DrawBufferInfo (bool render, const IVec2& size, const BlendState& blendState, const TextureFormat& format)
    290 	: m_render		(render)
    291 	, m_size		(size)
    292 	, m_format		(format)
    293 	, m_blendState	(blendState)
    294 {
    295 }
    296 
    297 void clearRenderbuffer (const glw::Functions&			gl,
    298 						const tcu::TextureFormat&		format,
    299 						int								renderbufferNdx,
    300 						int								renderbufferCount,
    301 						tcu::TextureLevel&				refRenderbuffer)
    302 {
    303 	const tcu::TextureFormatInfo	info		= tcu::getTextureFormatInfo(format);
    304 
    305 	// Clear each buffer to different color
    306 	const float						redScale	= float(renderbufferNdx + 1) / float(renderbufferCount);
    307 	const float						blueScale	= float(renderbufferCount - renderbufferNdx) / float(renderbufferCount);
    308 	const float						greenScale	= float(((renderbufferCount/2) + renderbufferNdx) % renderbufferCount) / float(renderbufferCount);
    309 	// Alpha should never be zero as advanced blend equations assume premultiplied alpha.
    310 	const float						alphaScale	= float(1 + (((renderbufferCount/2) + renderbufferCount - renderbufferNdx) % renderbufferCount)) / float(renderbufferCount);
    311 
    312 	switch (tcu::getTextureChannelClass(format.type))
    313 	{
    314 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    315 		{
    316 			const float red		= -1000.0f + 2000.0f * redScale;
    317 			const float green	= -1000.0f + 2000.0f * greenScale;
    318 			const float blue	= -1000.0f + 2000.0f * blueScale;
    319 			const float alpha	= -1000.0f + 2000.0f * alphaScale;
    320 			const Vec4	color	(red, green, blue, alpha);
    321 
    322 			tcu::clear(refRenderbuffer, color);
    323 			gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
    324 			break;
    325 		}
    326 
    327 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    328 		{
    329 			const deInt32	red		= deInt32(info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale);
    330 			const deInt32	green	= deInt32(info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale);
    331 			const deInt32	blue	= deInt32(info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale);
    332 			const deInt32	alpha	= deInt32(info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale);
    333 			const IVec4		color	(red, green, blue, alpha);
    334 
    335 			tcu::clear(refRenderbuffer, color);
    336 			gl.clearBufferiv(GL_COLOR, renderbufferNdx, color.getPtr());
    337 			break;
    338 		}
    339 
    340 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    341 		{
    342 			const deUint32	red		= deUint32(info.valueMax.x() * redScale);
    343 			const deUint32	green	= deUint32(info.valueMax.y() * greenScale);
    344 			const deUint32	blue	= deUint32(info.valueMax.z() * blueScale);
    345 			const deUint32	alpha	= deUint32(info.valueMax.w() * alphaScale);
    346 			const UVec4		color	(red, green, blue, alpha);
    347 
    348 			tcu::clear(refRenderbuffer, color);
    349 			gl.clearBufferuiv(GL_COLOR, renderbufferNdx, color.getPtr());
    350 			break;
    351 		}
    352 
    353 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    354 		{
    355 			const float red		= info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale;
    356 			const float green	= info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale;
    357 			const float blue	= info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale;
    358 			const float alpha	= info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale;
    359 			const Vec4	color	(red, green, blue, alpha);
    360 
    361 			tcu::clear(refRenderbuffer, color);
    362 			gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
    363 			break;
    364 		}
    365 
    366 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    367 		{
    368 			const float red		= info.valueMax.x() * redScale;
    369 			const float green	= info.valueMax.y() * greenScale;
    370 			const float blue	= info.valueMax.z() * blueScale;
    371 			const float alpha	= info.valueMax.w() * alphaScale;
    372 			const Vec4	color	(red, green, blue, alpha);
    373 
    374 			tcu::clear(refRenderbuffer, color);
    375 			gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr());
    376 			break;
    377 		}
    378 
    379 		default:
    380 			DE_ASSERT(DE_FALSE);
    381 	}
    382 
    383 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear renderbuffer.");
    384 }
    385 
    386 void genRenderbuffers (const glw::Functions&			gl,
    387 					   const vector<DrawBufferInfo>&	drawBuffers,
    388 					   const glu::Framebuffer&			framebuffer,
    389 					   const glu::RenderbufferVector&	renderbuffers,
    390 					   vector<TextureLevel>&			refRenderbuffers)
    391 {
    392 	vector<deUint32> bufs;
    393 
    394 	bufs.resize(drawBuffers.size());
    395 
    396 	DE_ASSERT(drawBuffers.size() == renderbuffers.size());
    397 	DE_ASSERT(drawBuffers.size() == refRenderbuffers.size());
    398 
    399 	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
    400 
    401 	for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
    402 	{
    403 		const DrawBufferInfo&		drawBuffer	= drawBuffers[renderbufferNdx];
    404 		const TextureFormat&		format		= drawBuffer.getFormat();
    405 		const IVec2&				size		= drawBuffer.getSize();
    406 		const deUint32				glFormat	= glu::getInternalFormat(format);
    407 
    408 		bufs[renderbufferNdx]					= GL_COLOR_ATTACHMENT0 + renderbufferNdx;
    409 		refRenderbuffers[renderbufferNdx]		= TextureLevel(drawBuffer.getFormat(), size.x(), size.y());
    410 
    411 		gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
    412 		gl.renderbufferStorage(GL_RENDERBUFFER, glFormat, size.x(), size.y());
    413 		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + renderbufferNdx, GL_RENDERBUFFER, renderbuffers[renderbufferNdx]);
    414 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create renderbuffer.");
    415 	}
    416 
    417 	gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
    418 
    419 	for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
    420 	{
    421 		const DrawBufferInfo&		drawBuffer	= drawBuffers[renderbufferNdx];
    422 		const TextureFormat&		format		= drawBuffer.getFormat();
    423 
    424 		clearRenderbuffer(gl, format, renderbufferNdx, (int)refRenderbuffers.size(),  refRenderbuffers[renderbufferNdx]);
    425 	}
    426 
    427 	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
    428 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
    429 }
    430 
    431 Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
    432 {
    433 	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
    434 	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
    435 
    436 	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
    437 	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
    438 
    439 	DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
    440 	DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
    441 
    442 	const tcu::IVec4	srcBits		= tcu::getTextureFormatBitDepth(sourceFormat);
    443 	const tcu::IVec4	readBits	= tcu::getTextureFormatBitDepth(readPixelsFormat);
    444 
    445 	return Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>();
    446 }
    447 
    448 void verifyRenderbuffer (TestLog&					log,
    449 						 tcu::ResultCollector&		results,
    450 						 const tcu::TextureFormat&	format,
    451 						 int						renderbufferNdx,
    452 						 const tcu::TextureLevel&	refRenderbuffer,
    453 						 const tcu::TextureLevel&	result)
    454 {
    455 	switch (tcu::getTextureChannelClass(format.type))
    456 	{
    457 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    458 		{
    459 			const string	name		= "Renderbuffer" + de::toString(renderbufferNdx);
    460 			const string	desc		= "Compare renderbuffer " + de::toString(renderbufferNdx);
    461 			const UVec4		threshold	(1, 1, 1, 1);
    462 
    463 			if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
    464 				results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
    465 
    466 			break;
    467 		}
    468 
    469 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    470 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    471 		{
    472 			const string	name		= "Renderbuffer" + de::toString(renderbufferNdx);
    473 			const string	desc		= "Compare renderbuffer " + de::toString(renderbufferNdx);
    474 			const UVec4		threshold	(1, 1, 1, 1);
    475 
    476 			if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
    477 				results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
    478 
    479 			break;
    480 		}
    481 
    482 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    483 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    484 		{
    485 			const string	name		= "Renderbuffer" + de::toString(renderbufferNdx);
    486 			const string	desc		= "Compare renderbuffer " + de::toString(renderbufferNdx);
    487 			const Vec4		threshold	= getFixedPointFormatThreshold(format, result.getFormat());
    488 
    489 			if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
    490 				results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
    491 
    492 			break;
    493 		}
    494 
    495 
    496 		default:
    497 			DE_ASSERT(DE_FALSE);
    498 	}
    499 }
    500 
    501 TextureFormat getReadPixelFormat (const TextureFormat& format)
    502 {
    503 	switch (tcu::getTextureChannelClass(format.type))
    504 	{
    505 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    506 			return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32);
    507 
    508 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    509 			return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32);
    510 
    511 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    512 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    513 			return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
    514 
    515 		default:
    516 			DE_ASSERT(false);
    517 			return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
    518 	}
    519 }
    520 
    521 void verifyRenderbuffers (TestLog&							log,
    522 						  tcu::ResultCollector&				results,
    523 						  glu::RenderContext&				renderContext,
    524 						  const glu::RenderbufferVector&	renderbuffers,
    525 						  const glu::Framebuffer&			framebuffer,
    526 						  const vector<TextureLevel>&		refRenderbuffers)
    527 {
    528 	const glw::Functions& gl = renderContext.getFunctions();
    529 
    530 	DE_ASSERT(renderbuffers.size() == refRenderbuffers.size());
    531 
    532 	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
    533 
    534 	for (int renderbufferNdx = 0; renderbufferNdx < (int)renderbuffers.size(); renderbufferNdx++)
    535 	{
    536 		const TextureLevel&	refRenderbuffer	= refRenderbuffers[renderbufferNdx];
    537 		const int			width			= refRenderbuffer.getWidth();
    538 		const int			height			= refRenderbuffer.getHeight();
    539 		const TextureFormat	format			= refRenderbuffer.getFormat();
    540 
    541 		tcu::TextureLevel	result			(getReadPixelFormat(format), width, height);
    542 
    543 		gl.readBuffer(GL_COLOR_ATTACHMENT0 + renderbufferNdx);
    544 		glu::readPixels(renderContext, 0, 0, result.getAccess());
    545 		GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels from renderbuffer failed.");
    546 
    547 		verifyRenderbuffer(log, results, format, renderbufferNdx, refRenderbuffer, result);
    548 	}
    549 
    550 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
    551 }
    552 
    553 static const float s_quadCoords[] =
    554 {
    555 	-0.5f, -0.5f,
    556 	 0.5f, -0.5f,
    557 	 0.5f,  0.5f,
    558 
    559 	 0.5f,  0.5f,
    560 	-0.5f,  0.5f,
    561 	-0.5f, -0.5f
    562 };
    563 
    564 void setBlendState (rr::FragmentOperationState& fragOps, const BlendState& state)
    565 {
    566 	if (state.blendEq)
    567 	{
    568 		if (state.blendEq->is<BlendEq>())
    569 		{
    570 			if (isAdvancedBlendEq(state.blendEq->get<BlendEq>()))
    571 			{
    572 				const rr::BlendEquationAdvanced	equation = mapGLBlendEquationAdvanced(state.blendEq->get<BlendEq>());
    573 
    574 				fragOps.blendMode				= rr::BLENDMODE_ADVANCED;
    575 				fragOps.blendEquationAdvaced	= equation;
    576 			}
    577 			else
    578 			{
    579 				const rr::BlendEquation equation = mapGLBlendEquation(state.blendEq->get<BlendEq>());
    580 
    581 				fragOps.blendMode				= rr::BLENDMODE_STANDARD;
    582 				fragOps.blendRGBState.equation	= equation;
    583 				fragOps.blendAState.equation	= equation;
    584 			}
    585 		}
    586 		else
    587 		{
    588 			DE_ASSERT(state.blendEq->is<SeparateBlendEq>());
    589 
    590 			fragOps.blendMode				= rr::BLENDMODE_STANDARD;
    591 			fragOps.blendRGBState.equation	= mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().rgb);
    592 			fragOps.blendAState.equation	= mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().alpha);
    593 		}
    594 	}
    595 
    596 	if (state.blendFunc)
    597 	{
    598 		if (state.blendFunc->is<BlendFunc>())
    599 		{
    600 			const rr::BlendFunc srcFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().src);
    601 			const rr::BlendFunc dstFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().dst);
    602 
    603 			fragOps.blendRGBState.srcFunc	= srcFunction;
    604 			fragOps.blendRGBState.dstFunc	= dstFunction;
    605 
    606 			fragOps.blendAState.srcFunc		= srcFunction;
    607 			fragOps.blendAState.dstFunc		= dstFunction;
    608 		}
    609 		else
    610 		{
    611 			DE_ASSERT(state.blendFunc->is<SeparateBlendFunc>());
    612 
    613 			fragOps.blendRGBState.srcFunc	= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.src);
    614 			fragOps.blendRGBState.dstFunc	= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.dst);
    615 
    616 			fragOps.blendAState.srcFunc		= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.src);
    617 			fragOps.blendAState.dstFunc		= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.dst);
    618 		}
    619 	}
    620 
    621 	if (state.colorMask)
    622 		fragOps.colorMask = *state.colorMask;
    623 }
    624 
    625 rr::RenderState createRenderState (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const DrawBufferInfo& info)
    626 {
    627 	const IVec2		size	= info.getSize();
    628 	rr::RenderState	state	(rr::ViewportState(rr::WindowRectangle(0, 0, size.x(), size.y())));
    629 
    630 	state.fragOps.blendMode = rr::BLENDMODE_STANDARD;
    631 
    632 	setBlendState(state.fragOps, preCommonBlendState);
    633 	setBlendState(state.fragOps, info.getBlendState());
    634 	setBlendState(state.fragOps, postCommonBlendState);
    635 
    636 	if (postCommonBlendState.enableBlend)
    637 		state.fragOps.blendMode = (*(postCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
    638 	else  if (info.getBlendState().enableBlend)
    639 		state.fragOps.blendMode = (*(info.getBlendState().enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
    640 	else if (preCommonBlendState.enableBlend)
    641 		state.fragOps.blendMode = (*(preCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
    642 	else
    643 		state.fragOps.blendMode = rr::BLENDMODE_NONE;
    644 
    645 	if (tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT && tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
    646 		state.fragOps.blendMode = rr::BLENDMODE_NONE;
    647 
    648 	return state;
    649 }
    650 
    651 class VertexShader : public rr::VertexShader
    652 {
    653 public:
    654 					VertexShader	(void);
    655 	virtual void	shadeVertices	(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
    656 };
    657 
    658 VertexShader::VertexShader (void)
    659 	: rr::VertexShader	(1, 1)
    660 {
    661 	m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    662 	m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    663 }
    664 
    665 void VertexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
    666 {
    667 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    668 	{
    669 		rr::VertexPacket& packet = *packets[packetNdx];
    670 
    671 		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
    672 		packet.outputs[0]	= 0.5f * (Vec4(1.0f) + rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx));
    673 	}
    674 }
    675 
    676 class FragmentShader : public rr::FragmentShader
    677 {
    678 public:
    679 			FragmentShader	(int drawBufferNdx, const DrawBufferInfo& info);
    680 	void	shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
    681 
    682 private:
    683 	const int				m_drawBufferNdx;
    684 	const DrawBufferInfo	m_info;
    685 };
    686 
    687 FragmentShader::FragmentShader (int drawBufferNdx, const DrawBufferInfo& info)
    688 	: rr::FragmentShader	(1, 1)
    689 	, m_drawBufferNdx		(drawBufferNdx)
    690 	, m_info				(info)
    691 {
    692 	m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
    693 
    694 	switch (tcu::getTextureChannelClass(m_info.getFormat().type))
    695 	{
    696 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    697 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    698 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    699 			m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
    700 			break;
    701 
    702 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    703 			m_outputs[0].type = rr::GENERICVECTYPE_UINT32;
    704 			break;
    705 
    706 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    707 			m_outputs[0].type = rr::GENERICVECTYPE_INT32;
    708 			break;
    709 
    710 		default:
    711 			DE_ASSERT(false);
    712 	};
    713 }
    714 
    715 void FragmentShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
    716 {
    717 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    718 	{
    719 		rr::FragmentPacket& packet = packets[packetNdx];
    720 
    721 		DE_ASSERT(m_drawBufferNdx >= 0);
    722 		DE_UNREF(m_info);
    723 
    724 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
    725 		{
    726 			const Vec2	vColor		= rr::readVarying<float>(packet, context, 0, fragNdx).xy();
    727 			const float	values[]	=
    728 			{
    729 				vColor.x(),
    730 				vColor.y(),
    731 				(1.0f - vColor.x()),
    732 				(1.0f - vColor.y())
    733 			};
    734 
    735 			switch (tcu::getTextureChannelClass(m_info.getFormat().type))
    736 			{
    737 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    738 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    739 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    740 				{
    741 					const Vec4 color (values[(m_drawBufferNdx + 0) % 4],
    742 									  values[(m_drawBufferNdx + 1) % 4],
    743 									  values[(m_drawBufferNdx + 2) % 4],
    744 									  values[(m_drawBufferNdx + 3) % 4]);
    745 
    746 					rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
    747 					break;
    748 				}
    749 
    750 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    751 				{
    752 					const UVec4 color ((deUint32)(values[(m_drawBufferNdx + 0) % 4]),
    753 									   (deUint32)(values[(m_drawBufferNdx + 1) % 4]),
    754 									   (deUint32)(values[(m_drawBufferNdx + 2) % 4]),
    755 									   (deUint32)(values[(m_drawBufferNdx + 3) % 4]));
    756 
    757 					rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
    758 					break;
    759 				}
    760 
    761 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    762 				{
    763 					const IVec4 color ((deInt32)(values[(m_drawBufferNdx + 0) % 4]),
    764 									   (deInt32)(values[(m_drawBufferNdx + 1) % 4]),
    765 									   (deInt32)(values[(m_drawBufferNdx + 2) % 4]),
    766 									   (deInt32)(values[(m_drawBufferNdx + 3) % 4]));
    767 
    768 					rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
    769 					break;
    770 				}
    771 
    772 				default:
    773 					DE_ASSERT(DE_FALSE);
    774 			};
    775 		}
    776 	}
    777 }
    778 
    779 rr::VertexAttrib createVertexAttrib (const float* coords)
    780 {
    781 	rr::VertexAttrib attrib;
    782 
    783 	attrib.type		= rr::VERTEXATTRIBTYPE_FLOAT;
    784 	attrib.size		= 2;
    785 	attrib.pointer	= coords;
    786 
    787 	return attrib;
    788 }
    789 
    790 void renderRefQuad (const BlendState&				preCommonBlendState,
    791 					const BlendState&				postCommonBlendState,
    792 					const vector<DrawBufferInfo>&	drawBuffers,
    793 					vector<TextureLevel>&			refRenderbuffers)
    794 {
    795 	const rr::Renderer			renderer;
    796 	const rr::PrimitiveList		primitives		(rr::PRIMITIVETYPE_TRIANGLES, 6, 0);
    797 	const rr::VertexAttrib		vertexAttribs[] =
    798 	{
    799 		createVertexAttrib(s_quadCoords)
    800 	};
    801 
    802 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
    803 	{
    804 		if (drawBuffers[drawBufferNdx].getRender())
    805 		{
    806 			const rr::RenderState	renderState		(createRenderState(preCommonBlendState, postCommonBlendState, drawBuffers[drawBufferNdx]));
    807 			const rr::RenderTarget	renderTarget	(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refRenderbuffers[drawBufferNdx].getAccess()));
    808 			const VertexShader		vertexShader;
    809 			const FragmentShader	fragmentShader	(drawBufferNdx, drawBuffers[drawBufferNdx]);
    810 			const rr::Program		program			(&vertexShader, &fragmentShader);
    811 			const rr::DrawCommand	command			(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, primitives);
    812 
    813 			renderer.draw(command);
    814 		}
    815 	}
    816 }
    817 
    818 bool requiresAdvancedBlendEq (const BlendState& pre, const BlendState post, const vector<DrawBufferInfo>& drawBuffers)
    819 {
    820 	bool requiresAdvancedBlendEq = false;
    821 
    822 	if (pre.blendEq && pre.blendEq->is<BlendEq>())
    823 		requiresAdvancedBlendEq |= isAdvancedBlendEq(pre.blendEq->get<BlendEq>());
    824 
    825 	if (post.blendEq && post.blendEq->is<BlendEq>())
    826 		requiresAdvancedBlendEq |= isAdvancedBlendEq(post.blendEq->get<BlendEq>());
    827 
    828 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
    829 	{
    830 		const BlendState& drawBufferBlendState = drawBuffers[drawBufferNdx].getBlendState();
    831 
    832 		if (drawBufferBlendState.blendEq && drawBufferBlendState.blendEq->is<BlendEq>())
    833 			requiresAdvancedBlendEq |= isAdvancedBlendEq(drawBufferBlendState.blendEq->get<BlendEq>());
    834 	}
    835 
    836 	return requiresAdvancedBlendEq;
    837 }
    838 
    839 glu::VertexSource genVertexSource (void)
    840 {
    841 	const char* const vertexSource =
    842 		"#version 310 es\n"
    843 		"layout(location=0) in highp vec2 i_coord;\n"
    844 		"out highp vec2 v_color;\n"
    845 		"void main (void)\n"
    846 		"{\n"
    847 		"\tv_color = 0.5 * (vec2(1.0) + i_coord);\n"
    848 		"\tgl_Position = vec4(i_coord, 0.0, 1.0);\n"
    849 		"}";
    850 
    851 	return glu::VertexSource(vertexSource);
    852 }
    853 
    854 glu::FragmentSource genFragmentSource (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers)
    855 {
    856 	std::ostringstream stream;
    857 
    858 	stream << "#version 310 es\n";
    859 
    860 	if (requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers))
    861 	{
    862 		stream << "#extension GL_KHR_blend_equation_advanced : require\n"
    863 			   <<  "layout(blend_support_all_equations) out;\n";
    864 	}
    865 
    866 	stream << "in highp vec2 v_color;\n";
    867 
    868 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
    869 	{
    870 		const DrawBufferInfo&	drawBuffer			= drawBuffers[drawBufferNdx];
    871 		const TextureFormat&	format				= drawBuffer.getFormat();
    872 
    873 		stream << "layout(location=" << drawBufferNdx << ") out highp ";
    874 
    875 		switch (tcu::getTextureChannelClass(format.type))
    876 		{
    877 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    878 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    879 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    880 				stream << "vec4";
    881 				break;
    882 
    883 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    884 				stream << "uvec4";
    885 				break;
    886 
    887 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    888 				stream << "ivec4";
    889 				break;
    890 
    891 			default:
    892 				DE_ASSERT(DE_FALSE);
    893 		};
    894 
    895 		stream << " o_drawBuffer" <<  drawBufferNdx << ";\n";
    896 	}
    897 
    898 	stream << "void main (void)\n"
    899 		   << "{\n";
    900 
    901 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
    902 	{
    903 		const DrawBufferInfo&	drawBuffer		= drawBuffers[drawBufferNdx];
    904 		const TextureFormat&	format			= drawBuffer.getFormat();
    905 		const char* const		values[]		=
    906 		{
    907 			"v_color.x",
    908 			"v_color.y",
    909 			"(1.0 - v_color.x)",
    910 			"(1.0 - v_color.y)"
    911 		};
    912 
    913 		stream << "\to_drawBuffer" <<  drawBufferNdx;
    914 
    915 		switch (tcu::getTextureChannelClass(format.type))
    916 		{
    917 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    918 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    919 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    920 				stream << " = vec4(" << values[(drawBufferNdx + 0) % 4]
    921 					   << ", " << values[(drawBufferNdx + 1) % 4]
    922 					   << ", " << values[(drawBufferNdx + 2) % 4]
    923 					   << ", " << values[(drawBufferNdx + 3) % 4] << ");\n";
    924 				break;
    925 
    926 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    927 				stream << " = uvec4(uint(" << values[(drawBufferNdx + 0) % 4]
    928 					   << "), uint(" << values[(drawBufferNdx + 1) % 4]
    929 					   << "), uint(" << values[(drawBufferNdx + 2) % 4]
    930 					   << "), uint(" << values[(drawBufferNdx + 3) % 4] << "));\n";
    931 				break;
    932 
    933 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    934 				stream << " = ivec4(int(" << values[(drawBufferNdx + 0) % 4]
    935 					   << "), int(" << values[(drawBufferNdx + 1) % 4]
    936 					   << "), int(" << values[(drawBufferNdx + 2) % 4]
    937 					   << "), int(" << values[(drawBufferNdx + 3) % 4] << "));\n";
    938 				break;
    939 
    940 			default:
    941 				DE_ASSERT(DE_FALSE);
    942 		};
    943 	}
    944 
    945 	stream << "}";
    946 
    947 	return glu::FragmentSource(stream.str());
    948 }
    949 
    950 glu::ProgramSources genShaderSources (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers)
    951 {
    952 	return glu::ProgramSources() << genVertexSource() << genFragmentSource(preCommonBlendState, postCommonBlendState, drawBuffers);
    953 }
    954 
    955 void renderGLQuad (glu::RenderContext&			renderContext,
    956 				   const glu::ShaderProgram&	program)
    957 {
    958 	const glu::VertexArrayBinding vertexArrays[] =
    959 	{
    960 		glu::VertexArrayBinding(glu::BindingPoint(0), glu::VertexArrayPointer(glu::VTX_COMP_FLOAT, glu::VTX_COMP_CONVERT_NONE, 2, 6, 0, s_quadCoords))
    961 	};
    962 
    963 	glu::draw(renderContext, program.getProgram(), 1, vertexArrays, glu::pr::Triangles(6));
    964 }
    965 
    966 void renderQuad (TestLog&						log,
    967 				 glu::RenderContext&			renderContext,
    968 				 const BlendState&				preCommonBlendState,
    969 				 const BlendState&				postCommonBlendState,
    970 				 const vector<DrawBufferInfo>&	drawBuffers,
    971 				 const glu::Framebuffer&		framebuffer,
    972 				 vector<TextureLevel>&			refRenderbuffers)
    973 {
    974 	const glw::Functions&		gl						= renderContext.getFunctions();
    975 	const glu::ShaderProgram	program					(gl, genShaderSources(preCommonBlendState, postCommonBlendState, drawBuffers));
    976 	const IVec2					size					= drawBuffers[0].getSize();
    977 	const bool					requiresBlendBarriers	= requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers);
    978 
    979 	vector<deUint32> bufs;
    980 
    981 	bufs.resize(drawBuffers.size());
    982 
    983 	for (int bufNdx = 0; bufNdx < (int)bufs.size(); bufNdx++)
    984 		bufs[bufNdx] = (drawBuffers[bufNdx].getRender() ? GL_COLOR_ATTACHMENT0 + bufNdx : GL_NONE);
    985 
    986 	log << program;
    987 
    988 	gl.viewport(0, 0, size.x(), size.y());
    989 	gl.useProgram(program.getProgram());
    990 	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
    991 
    992 	setCommonBlendState(gl, preCommonBlendState);
    993 
    994 	for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
    995 		setIndexedBlendState(gl, drawBuffers[renderbufferNdx].getBlendState(), renderbufferNdx);
    996 
    997 	setCommonBlendState(gl, postCommonBlendState);
    998 
    999 	gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
   1000 
   1001 	if (requiresBlendBarriers)
   1002 		gl.blendBarrierKHR();
   1003 
   1004 	renderGLQuad(renderContext, program);
   1005 
   1006 	if (requiresBlendBarriers)
   1007 		gl.blendBarrierKHR();
   1008 
   1009 	gl.drawBuffers(0, 0);
   1010 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
   1011 	gl.useProgram(0);
   1012 
   1013 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
   1014 
   1015 	renderRefQuad(preCommonBlendState, postCommonBlendState, drawBuffers, refRenderbuffers);
   1016 }
   1017 
   1018 void logBlendState (TestLog&			log,
   1019 					const BlendState&	blend)
   1020 {
   1021 	if (blend.enableBlend)
   1022 	{
   1023 		if (*blend.enableBlend)
   1024 			log << TestLog::Message << "Enable blending." << TestLog::EndMessage;
   1025 		else
   1026 			log << TestLog::Message << "Disable blending." << TestLog::EndMessage;
   1027 	}
   1028 
   1029 	if (blend.colorMask)
   1030 	{
   1031 		const BVec4 mask = *blend.colorMask;
   1032 
   1033 		log << TestLog::Message << "Set color mask: " << mask << "." << TestLog::EndMessage;
   1034 	}
   1035 
   1036 
   1037 	if (blend.blendEq)
   1038 	{
   1039 		const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
   1040 
   1041 		if (blendEq.is<BlendEq>())
   1042 			log << TestLog::Message << "Set blend equation: " << glu::getBlendEquationStr(blendEq.get<BlendEq>()) << "." << TestLog::EndMessage;
   1043 		else if (blendEq.is<SeparateBlendEq>())
   1044 			log << TestLog::Message << "Set blend equation rgb: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().rgb) << ", alpha: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().alpha) << "." << TestLog::EndMessage;
   1045 		else
   1046 			DE_ASSERT(false);
   1047 	}
   1048 
   1049 	if (blend.blendFunc)
   1050 	{
   1051 		const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
   1052 
   1053 		if (blendFunc.is<BlendFunc>())
   1054 			log << TestLog::Message << "Set blend function source: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().dst) << "." << TestLog::EndMessage;
   1055 		else if (blendFunc.is<SeparateBlendFunc>())
   1056 		{
   1057 			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;
   1058 			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;
   1059 		}
   1060 		else
   1061 			DE_ASSERT(false);
   1062 	}
   1063 }
   1064 
   1065 void logTestCaseInfo (TestLog&						log,
   1066 					  const BlendState&				preCommonBlendState,
   1067 					  const BlendState&				postCommonBlendState,
   1068 					  const vector<DrawBufferInfo>&	drawBuffers)
   1069 {
   1070 	{
   1071 		tcu::ScopedLogSection drawBuffersSection(log, "DrawBuffers", "Draw buffers");
   1072 
   1073 		for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
   1074 		{
   1075 			const tcu::ScopedLogSection	drawBufferSection	(log, "DrawBuffer" + de::toString(drawBufferNdx), "Draw Buffer " + de::toString(drawBufferNdx));
   1076 			const DrawBufferInfo&		drawBuffer			= drawBuffers[drawBufferNdx];
   1077 
   1078 			log << TestLog::Message << "Format: " << drawBuffer.getFormat() << TestLog::EndMessage;
   1079 			log << TestLog::Message << "Size: " << drawBuffer.getSize() << TestLog::EndMessage;
   1080 			log << TestLog::Message << "Render: " << (drawBuffer.getRender() ? "true" : "false") << TestLog::EndMessage;
   1081 		}
   1082 	}
   1083 
   1084 	if (!preCommonBlendState.isEmpty())
   1085 	{
   1086 		tcu::ScopedLogSection s(log, "PreCommonState", "First set common blend state");
   1087 		logBlendState(log, preCommonBlendState);
   1088 	}
   1089 
   1090 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
   1091 	{
   1092 		if (!drawBuffers[drawBufferNdx].getBlendState().isEmpty())
   1093 		{
   1094 			const tcu::ScopedLogSection s(log, "DrawBufferState" + de::toString(drawBufferNdx), "Set DrawBuffer " + de::toString(drawBufferNdx) + " state to");
   1095 
   1096 			logBlendState(log, drawBuffers[drawBufferNdx].getBlendState());
   1097 		}
   1098 	}
   1099 
   1100 	if (!postCommonBlendState.isEmpty())
   1101 	{
   1102 		tcu::ScopedLogSection s(log, "PostCommonState", "After set common blend state");
   1103 		logBlendState(log, postCommonBlendState);
   1104 	}
   1105 }
   1106 
   1107 void runTest (TestLog&						log,
   1108 			  tcu::ResultCollector&			results,
   1109 			  glu::RenderContext&			renderContext,
   1110 
   1111 			  const BlendState&				preCommonBlendState,
   1112 			  const BlendState&				postCommonBlendState,
   1113 			  const vector<DrawBufferInfo>&	drawBuffers)
   1114 {
   1115 	const glw::Functions&	gl					= renderContext.getFunctions();
   1116 	glu::RenderbufferVector	renderbuffers		(gl, drawBuffers.size());
   1117 	glu::Framebuffer		framebuffer			(gl);
   1118 	vector<TextureLevel>	refRenderbuffers	(drawBuffers.size());
   1119 
   1120 	logTestCaseInfo(log, preCommonBlendState, postCommonBlendState, drawBuffers);
   1121 
   1122 	genRenderbuffers(gl, drawBuffers, framebuffer, renderbuffers, refRenderbuffers);
   1123 
   1124 	renderQuad(log, renderContext, preCommonBlendState, postCommonBlendState, drawBuffers, framebuffer, refRenderbuffers);
   1125 
   1126 	verifyRenderbuffers(log, results, renderContext, renderbuffers, framebuffer, refRenderbuffers);
   1127 }
   1128 
   1129 class DrawBuffersIndexedTest : public TestCase
   1130 {
   1131 public:
   1132 					DrawBuffersIndexedTest (Context&						context,
   1133 											const BlendState&				preCommonBlendState,
   1134 											const BlendState&				postCommonBlendState,
   1135 											const vector<DrawBufferInfo>&	drawBuffers,
   1136 											const string&					name,
   1137 											const string&					description);
   1138 
   1139 	void			init					(void);
   1140 	IterateResult	iterate					(void);
   1141 
   1142 private:
   1143 	const BlendState				m_preCommonBlendState;
   1144 	const BlendState				m_postCommonBlendState;
   1145 	const vector<DrawBufferInfo>	m_drawBuffers;
   1146 };
   1147 
   1148 DrawBuffersIndexedTest::DrawBuffersIndexedTest (Context&						context,
   1149 												const BlendState&				preCommonBlendState,
   1150 												const BlendState&				postCommonBlendState,
   1151 												const vector<DrawBufferInfo>&	drawBuffers,
   1152 												const string&					name,
   1153 												const string&					description)
   1154 	: TestCase					(context, name.c_str(), description.c_str())
   1155 	, m_preCommonBlendState		(preCommonBlendState)
   1156 	, m_postCommonBlendState	(postCommonBlendState)
   1157 	, m_drawBuffers				(drawBuffers)
   1158 {
   1159 }
   1160 
   1161 void DrawBuffersIndexedTest::init (void)
   1162 {
   1163 	if (requiresAdvancedBlendEq(m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers) && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
   1164 		throw tcu::NotSupportedError("Extension GL_KHR_blend_equation_advanced not supported", "", __FILE__, __LINE__);
   1165 
   1166 	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
   1167 		throw tcu::NotSupportedError("Extension GL_EXT_draw_buffers_indexed not supported", "", __FILE__, __LINE__);
   1168 }
   1169 
   1170 TestCase::IterateResult DrawBuffersIndexedTest::iterate (void)
   1171 {
   1172 	TestLog&				log		= m_testCtx.getLog();
   1173 	tcu::ResultCollector	results	(log);
   1174 
   1175 	runTest(log, results, m_context.getRenderContext(), m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers);
   1176 
   1177 	results.setTestContextResult(m_testCtx);
   1178 
   1179 	return STOP;
   1180 }
   1181 
   1182 BlendEq getRandomBlendEq (de::Random& rng)
   1183 {
   1184 	const BlendEq eqs[] =
   1185 	{
   1186 		GL_FUNC_ADD,
   1187 		GL_FUNC_SUBTRACT,
   1188 		GL_FUNC_REVERSE_SUBTRACT,
   1189 		GL_MIN,
   1190 		GL_MAX
   1191 	};
   1192 
   1193 	return de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(eqs)>(eqs, rng.getUint32() % DE_LENGTH_OF_ARRAY(eqs));
   1194 }
   1195 
   1196 BlendFunc getRandomBlendFunc (de::Random& rng)
   1197 {
   1198 	const deUint32 funcs[] =
   1199 	{
   1200 		GL_ZERO,
   1201 		GL_ONE,
   1202 		GL_SRC_COLOR,
   1203 		GL_ONE_MINUS_SRC_COLOR,
   1204 		GL_DST_COLOR,
   1205 		GL_ONE_MINUS_DST_COLOR,
   1206 		GL_SRC_ALPHA,
   1207 		GL_ONE_MINUS_SRC_ALPHA,
   1208 		GL_DST_ALPHA,
   1209 		GL_ONE_MINUS_DST_ALPHA,
   1210 		GL_CONSTANT_COLOR,
   1211 		GL_ONE_MINUS_CONSTANT_COLOR,
   1212 		GL_CONSTANT_ALPHA,
   1213 		GL_ONE_MINUS_CONSTANT_ALPHA,
   1214 		GL_SRC_ALPHA_SATURATE
   1215 	};
   1216 
   1217 	const deUint32 src = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
   1218 	const deUint32 dst = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
   1219 
   1220 	return BlendFunc(src, dst);
   1221 }
   1222 
   1223 void genRandomBlendState (de::Random& rng, BlendState& blendState)
   1224 {
   1225 	if (rng.getBool())
   1226 		blendState.enableBlend = rng.getBool();
   1227 
   1228 	if (rng.getBool())
   1229 	{
   1230 		if (rng.getBool())
   1231 			blendState.blendEq = getRandomBlendEq(rng);
   1232 		else
   1233 		{
   1234 			const BlendEq	rgb		= getRandomBlendEq(rng);
   1235 			const BlendEq	alpha	= getRandomBlendEq(rng);
   1236 
   1237 			blendState.blendEq		= SeparateBlendEq(rgb, alpha);
   1238 		}
   1239 	}
   1240 
   1241 	if (rng.getBool())
   1242 	{
   1243 		if (rng.getBool())
   1244 			blendState.blendFunc = getRandomBlendFunc(rng);
   1245 		else
   1246 		{
   1247 			const BlendFunc	rgb		= getRandomBlendFunc(rng);
   1248 			const BlendFunc	alpha	= getRandomBlendFunc(rng);
   1249 
   1250 			blendState.blendFunc	= SeparateBlendFunc(rgb, alpha);
   1251 		}
   1252 	}
   1253 
   1254 	if (rng.getBool())
   1255 	{
   1256 		const bool red		= rng.getBool();
   1257 		const bool green	= rng.getBool();
   1258 		const bool blue		= rng.getBool();
   1259 		const bool alpha	= rng.getBool();
   1260 
   1261 		blendState.colorMask = BVec4(red, blue, green, alpha);
   1262 	}
   1263 }
   1264 
   1265 TextureFormat getRandomFormat (de::Random& rng)
   1266 {
   1267 	const deUint32 glFormats[] =
   1268 	{
   1269 		GL_R8,
   1270 		GL_RG8,
   1271 		GL_RGB8,
   1272 		GL_RGB565,
   1273 		GL_RGBA4,
   1274 		GL_RGB5_A1,
   1275 		GL_RGBA8,
   1276 		GL_RGB10_A2,
   1277 		GL_RGB10_A2UI,
   1278 		GL_R8I,
   1279 		GL_R8UI,
   1280 		GL_R16I,
   1281 		GL_R16UI,
   1282 		GL_R32I,
   1283 		GL_R32UI,
   1284 		GL_RG8I,
   1285 		GL_RG8UI,
   1286 		GL_RG16I,
   1287 		GL_RG16UI,
   1288 		GL_RG32I,
   1289 		GL_RG32UI,
   1290 		GL_RGBA8I,
   1291 		GL_RGBA8UI,
   1292 		GL_RGBA16I,
   1293 		GL_RGBA16UI,
   1294 		GL_RGBA32I,
   1295 		GL_RGBA32UI
   1296 	};
   1297 
   1298 	return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % DE_LENGTH_OF_ARRAY(glFormats)));
   1299 }
   1300 
   1301 void genRandomTest (de::Random& rng, BlendState& preCommon, BlendState& postCommon, vector<DrawBufferInfo>& drawBuffers, int maxDrawBufferCount)
   1302 {
   1303 	genRandomBlendState(rng, preCommon);
   1304 	genRandomBlendState(rng, postCommon);
   1305 
   1306 	for (int drawBufferNdx = 0; drawBufferNdx < maxDrawBufferCount; drawBufferNdx++)
   1307 	{
   1308 		const bool			render		= rng.getFloat() > 0.1f;
   1309 		const IVec2			size		(64, 64);
   1310 		const TextureFormat	format		(getRandomFormat(rng));
   1311 		BlendState			blendState;
   1312 
   1313 		genRandomBlendState(rng, blendState);
   1314 		drawBuffers.push_back(DrawBufferInfo(render, size, blendState, format));
   1315 	}
   1316 }
   1317 
   1318 class MaxDrawBuffersIndexedTest : public TestCase
   1319 {
   1320 public:
   1321 					MaxDrawBuffersIndexedTest	(Context& contet, int seed);
   1322 
   1323 	void			init						(void);
   1324 	IterateResult	iterate						(void);
   1325 
   1326 private:
   1327 	const int		m_seed;
   1328 };
   1329 
   1330 MaxDrawBuffersIndexedTest::MaxDrawBuffersIndexedTest (Context& context, int seed)
   1331 	: TestCase	(context, de::toString(seed).c_str(), de::toString(seed).c_str())
   1332 	, m_seed	(deInt32Hash(seed) ^ 1558001307u)
   1333 {
   1334 }
   1335 
   1336 void MaxDrawBuffersIndexedTest::init (void)
   1337 {
   1338 	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
   1339 		throw tcu::NotSupportedError("Extension GL_EXT_draw_buffers_indexed not supported", "", __FILE__, __LINE__);
   1340 }
   1341 
   1342 TestCase::IterateResult MaxDrawBuffersIndexedTest::iterate (void)
   1343 {
   1344 	TestLog&				log						= m_testCtx.getLog();
   1345 	tcu::ResultCollector	results					(log);
   1346 	de::Random				rng						(m_seed);
   1347 	BlendState				preCommonBlendState;
   1348 	BlendState				postCommonBlendState;
   1349 	vector<DrawBufferInfo>	drawBuffers;
   1350 
   1351 	genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, 4);
   1352 
   1353 	runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
   1354 
   1355 	results.setTestContextResult(m_testCtx);
   1356 
   1357 	return STOP;
   1358 }
   1359 
   1360 class ImplMaxDrawBuffersIndexedTest : public TestCase
   1361 {
   1362 public:
   1363 					ImplMaxDrawBuffersIndexedTest	(Context& contet, int seed);
   1364 
   1365 	void			init							(void);
   1366 	IterateResult	iterate							(void);
   1367 
   1368 private:
   1369 	const int		m_seed;
   1370 };
   1371 
   1372 ImplMaxDrawBuffersIndexedTest::ImplMaxDrawBuffersIndexedTest (Context& context, int seed)
   1373 	: TestCase	(context, de::toString(seed).c_str(), de::toString(seed).c_str())
   1374 	, m_seed	(deInt32Hash(seed) ^ 2686315738u)
   1375 {
   1376 }
   1377 
   1378 void ImplMaxDrawBuffersIndexedTest::init (void)
   1379 {
   1380 	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
   1381 		throw tcu::NotSupportedError("Extension GL_EXT_draw_buffers_indexed not supported", "", __FILE__, __LINE__);
   1382 }
   1383 
   1384 TestCase::IterateResult ImplMaxDrawBuffersIndexedTest::iterate (void)
   1385 {
   1386 	TestLog&				log						= m_testCtx.getLog();
   1387 	tcu::ResultCollector	results					(log);
   1388 	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
   1389 	de::Random				rng						(m_seed);
   1390 	deInt32					maxDrawBuffers			= 0;
   1391 	BlendState				preCommonBlendState;
   1392 	BlendState				postCommonBlendState;
   1393 	vector<DrawBufferInfo>	drawBuffers;
   1394 
   1395 	gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
   1396 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_DRAW_BUFFERS) failed");
   1397 
   1398 	TCU_CHECK(maxDrawBuffers > 0);
   1399 
   1400 	genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, maxDrawBuffers);
   1401 
   1402 	runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
   1403 
   1404 	results.setTestContextResult(m_testCtx);
   1405 
   1406 	return STOP;
   1407 }
   1408 
   1409 enum PrePost
   1410 {
   1411 	PRE,
   1412 	POST
   1413 };
   1414 
   1415 TestCase* createDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
   1416 {
   1417 	const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
   1418 
   1419 	if (prepost == PRE)
   1420 	{
   1421 		const BlendState		preState	= BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
   1422 														 commonState.blendEq,
   1423 														 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
   1424 														 tcu::nothing<BVec4>());
   1425 		vector<DrawBufferInfo>	drawBuffers;
   1426 
   1427 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
   1428 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
   1429 
   1430 		return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
   1431 	}
   1432 	else if (prepost == POST)
   1433 	{
   1434 		const BlendState		preState	= BlendState(just(true),
   1435 														 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
   1436 														 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
   1437 														 tcu::nothing<BVec4>());
   1438 		vector<DrawBufferInfo>	drawBuffers;
   1439 
   1440 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
   1441 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
   1442 
   1443 		return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
   1444 	}
   1445 	else
   1446 	{
   1447 		DE_ASSERT(false);
   1448 		return DE_NULL;
   1449 	}
   1450 }
   1451 
   1452 TestCase* createAdvancedEqDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
   1453 {
   1454 	const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>());
   1455 
   1456 	if (prepost == PRE)
   1457 	{
   1458 		const BlendState		preState	= BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
   1459 														 commonState.blendEq,
   1460 														 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
   1461 														 tcu::nothing<BVec4>());
   1462 		vector<DrawBufferInfo>	drawBuffers;
   1463 
   1464 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
   1465 
   1466 		return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
   1467 	}
   1468 	else if (prepost == POST)
   1469 	{
   1470 		const BlendState		preState	= BlendState(just(true),
   1471 														 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(),
   1472 														 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
   1473 														 tcu::nothing<BVec4>());
   1474 		vector<DrawBufferInfo>	drawBuffers;
   1475 
   1476 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
   1477 
   1478 		return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
   1479 	}
   1480 	else
   1481 	{
   1482 		DE_ASSERT(false);
   1483 		return DE_NULL;
   1484 	}
   1485 }
   1486 
   1487 void addDrawBufferCommonTests (TestCaseGroup* root, PrePost prepost)
   1488 {
   1489 	const BlendState		emptyState	= BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1490 
   1491 	{
   1492 		const BlendState	disableState	= BlendState(just(false), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1493 		const BlendState	enableState		= BlendState(just(true), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1494 
   1495 		root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_enable",	enableState,	enableState));
   1496 		root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_disable",	disableState,	disableState));
   1497 		root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_enable",	disableState,	enableState));
   1498 		root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_disable",	enableState,	disableState));
   1499 	}
   1500 
   1501 	{
   1502 		const BlendState	eqStateA			= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_ADD), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1503 		const BlendState	eqStateB			= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_SUBTRACT), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1504 
   1505 		const BlendState	separateEqStateA	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_ADD, GL_FUNC_SUBTRACT)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1506 		const BlendState	separateEqStateB	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_SUBTRACT, GL_FUNC_ADD)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1507 
   1508 		const BlendState	advancedEqStateA	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_DIFFERENCE_KHR), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1509 		const BlendState	advancedEqStateB	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_SCREEN_KHR), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1510 
   1511 		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_blend_eq", eqStateA, eqStateB));
   1512 		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_separate_blend_eq", eqStateA, separateEqStateB));
   1513 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_advanced_blend_eq", eqStateA, advancedEqStateB));
   1514 
   1515 		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_blend_eq", separateEqStateA, eqStateB));
   1516 		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_separate_blend_eq", separateEqStateA, separateEqStateB));
   1517 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_advanced_blend_eq", separateEqStateA, advancedEqStateB));
   1518 
   1519 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_blend_eq", advancedEqStateA, eqStateB));
   1520 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_separate_blend_eq", advancedEqStateA, separateEqStateB));
   1521 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_advanced_blend_eq", advancedEqStateA, advancedEqStateB));
   1522 	}
   1523 
   1524 	{
   1525 		const BlendState	funcStateA			= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA)), Maybe<BVec4>());
   1526 		const BlendState	funcStateB			= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA)), Maybe<BVec4>());
   1527 		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>());
   1528 		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>());
   1529 
   1530 		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_blend_func",					funcStateA,			funcStateB));
   1531 		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_separate_blend_func",			funcStateA,			separateFuncStateB));
   1532 		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_blend_func",			separateFuncStateA,	funcStateB));
   1533 		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_separate_blend_func",	separateFuncStateA,	separateFuncStateB));
   1534 	}
   1535 
   1536 	{
   1537 		const BlendState	commonColorMaskState	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(true, false, true, false)));
   1538 		const BlendState	bufferColorMaskState	= BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(false, true, false, true)));
   1539 
   1540 		root->addChild(createDiffTest(root->getContext(), prepost, "common_color_mask_buffer_color_mask", commonColorMaskState, bufferColorMaskState));
   1541 	}
   1542 }
   1543 
   1544 void addRandomMaxTest (TestCaseGroup* root)
   1545 {
   1546 	for (int i = 0; i < 20; i++)
   1547 		root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i));
   1548 }
   1549 
   1550 void addRandomImplMaxTest (TestCaseGroup* root)
   1551 {
   1552 	for (int i = 0; i < 20; i++)
   1553 		root->addChild(new ImplMaxDrawBuffersIndexedTest(root->getContext(), i));
   1554 }
   1555 
   1556 } // anonymous
   1557 
   1558 TestCaseGroup* createDrawBuffersIndexedTests (Context& context)
   1559 {
   1560 	const BlendState		emptyState		= BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
   1561 	TestCaseGroup* const	group			= new TestCaseGroup(context, "draw_buffers_indexed", "Test for indexed draw buffers. GL_EXT_draw_buffers_indexed.");
   1562 
   1563 	TestCaseGroup* const	preGroup		= new TestCaseGroup(context, "overwrite_common", "Set common state and overwrite it with draw buffer blend state.");
   1564 	TestCaseGroup* const	postGroup		= new TestCaseGroup(context, "overwrite_indexed", "Set indexed blend state and overwrite it ith common state.");
   1565 	TestCaseGroup* const	randomGroup		= new TestCaseGroup(context, "random", "Random indexed blend state tests.");
   1566 	TestCaseGroup* const	maxGroup		= new TestCaseGroup(context, "max_required_draw_buffers", "Random tests using minimum maximum number of draw buffers.");
   1567 	TestCaseGroup* const	maxImplGroup	= new TestCaseGroup(context, "max_implementation_draw_buffers", "Random tests using maximum number of draw buffers reported by implementation.");
   1568 
   1569 	group->addChild(preGroup);
   1570 	group->addChild(postGroup);
   1571 	group->addChild(randomGroup);
   1572 
   1573 	randomGroup->addChild(maxGroup);
   1574 	randomGroup->addChild(maxImplGroup);
   1575 
   1576 	addDrawBufferCommonTests(preGroup, PRE);
   1577 	addDrawBufferCommonTests(postGroup, POST);
   1578 	addRandomMaxTest(maxGroup);
   1579 	addRandomImplMaxTest(maxImplGroup);
   1580 
   1581 	return group;
   1582 }
   1583 
   1584 } // Functional
   1585 } // gles31
   1586 } // deqp
   1587