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