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 
isAdvancedBlendEq(BlendEq eq)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 {
SeparateBlendEqdeqp::gles31::Functional::__anon169a63d40111::SeparateBlendEq119 	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 {
BlendFuncdeqp::gles31::Functional::__anon169a63d40111::BlendFunc131 	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 {
SeparateBlendFuncdeqp::gles31::Functional::__anon169a63d40111::SeparateBlendFunc143 	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 {
BlendStatedeqp::gles31::Functional::__anon169a63d40111::BlendState157 	BlendState (void) {}
158 
BlendStatedeqp::gles31::Functional::__anon169a63d40111::BlendState159 	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 
isEmptydeqp::gles31::Functional::__anon169a63d40111::BlendState170 	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 
setCommonBlendState(const glw::Functions & gl,const BlendState & blend)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 
setIndexedBlendState(const glw::Functions & gl,const BlendState & blend,deUint32 index)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 
getFormat(void) const277 	const TextureFormat&	getFormat		(void) const { return m_format;		}
getSize(void) const278 	const IVec2&			getSize			(void) const { return m_size;		}
getBlendState(void) const279 	const BlendState&		getBlendState	(void) const { return m_blendState;	}
getRender(void) const280 	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 
DrawBufferInfo(bool render,const IVec2 & size,const BlendState & blendState,const TextureFormat & format)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 
clearRenderbuffer(const glw::Functions & gl,const tcu::TextureFormat & format,int renderbufferNdx,int renderbufferCount,tcu::TextureLevel & refRenderbuffer)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 
genRenderbuffers(const glw::Functions & gl,const vector<DrawBufferInfo> & drawBuffers,const glu::Framebuffer & framebuffer,const glu::RenderbufferVector & renderbuffers,vector<TextureLevel> & refRenderbuffers)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 
getFixedPointFormatThreshold(const tcu::TextureFormat & sourceFormat,const tcu::TextureFormat & readPixelsFormat)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 
verifyRenderbuffer(TestLog & log,tcu::ResultCollector & results,const tcu::TextureFormat & format,int renderbufferNdx,const tcu::TextureLevel & refRenderbuffer,const tcu::TextureLevel & result)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 
getReadPixelFormat(const TextureFormat & format)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 
verifyRenderbuffers(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const glu::RenderbufferVector & renderbuffers,const glu::Framebuffer & framebuffer,const vector<TextureLevel> & refRenderbuffers)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 
setBlendState(rr::FragmentOperationState & fragOps,const BlendState & state)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 
createRenderState(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const DrawBufferInfo & info)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 
VertexShader(void)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 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const665 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 
FragmentShader(int drawBufferNdx,const DrawBufferInfo & info)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 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const715 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 
createVertexAttrib(const float * coords)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 
renderRefQuad(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,vector<TextureLevel> & refRenderbuffers)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 
requiresAdvancedBlendEq(const BlendState & pre,const BlendState post,const vector<DrawBufferInfo> & drawBuffers)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 
genVertexSource(void)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 
genFragmentSource(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)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 
genShaderSources(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)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 
renderGLQuad(glu::RenderContext & renderContext,const glu::ShaderProgram & program)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 
renderQuad(TestLog & log,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const glu::Framebuffer & framebuffer,vector<TextureLevel> & refRenderbuffers)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 
logBlendState(TestLog & log,const BlendState & blend)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 
logTestCaseInfo(TestLog & log,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)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 
runTest(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)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 
DrawBuffersIndexedTest(Context & context,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const string & name,const string & description)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 
init(void)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 
iterate(void)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 
getRandomBlendEq(de::Random & rng)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 
getRandomBlendFunc(de::Random & rng)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 
genRandomBlendState(de::Random & rng,BlendState & blendState)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 
getRandomFormat(de::Random & rng)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 
genRandomTest(de::Random & rng,BlendState & preCommon,BlendState & postCommon,vector<DrawBufferInfo> & drawBuffers,int maxDrawBufferCount)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 
MaxDrawBuffersIndexedTest(Context & context,int seed)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 
init(void)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 
iterate(void)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 
ImplMaxDrawBuffersIndexedTest(Context & context,int seed)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 
init(void)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 
iterate(void)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 
createDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)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 
createAdvancedEqDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)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 
addDrawBufferCommonTests(TestCaseGroup * root,PrePost prepost)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 
addRandomMaxTest(TestCaseGroup * root)1544 void addRandomMaxTest (TestCaseGroup* root)
1545 {
1546 	for (int i = 0; i < 20; i++)
1547 		root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i));
1548 }
1549 
addRandomImplMaxTest(TestCaseGroup * root)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 
createDrawBuffersIndexedTests(Context & context)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