• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3 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 "es3fDrawBuffersIndexedTests.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 gles3
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::gles3::Functional::__anon4df34afe0111::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::gles3::Functional::__anon4df34afe0111::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::gles3::Functional::__anon4df34afe0111::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::gles3::Functional::__anon4df34afe0111::BlendState161 	BlendState (void) {}
162 
BlendStatedeqp::gles3::Functional::__anon4df34afe0111::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::gles3::Functional::__anon4df34afe0111::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 	Vec4				threshold	= Vec4(0.0f);
457 
458 	for (int i = 0; i < 4; i++)
459 	{
460 		const int bits = de::min(srcBits[i], readBits[i]);
461 
462 		if (bits > 0)
463 		{
464 			threshold[i] = 3.0f / static_cast<float>(((1ul << bits) - 1ul));
465 		}
466 	}
467 
468 	return threshold;
469 }
470 
getFloatULPThreshold(const tcu::TextureFormat & sourceFormat,const tcu::TextureFormat & readPixelsFormat)471 UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
472 {
473 	const tcu::IVec4	srcMantissaBits		= tcu::getTextureFormatMantissaBitDepth(sourceFormat);
474 	const tcu::IVec4	readMantissaBits	= tcu::getTextureFormatMantissaBitDepth(readPixelsFormat);
475 	tcu::IVec4			ULPDiff(0);
476 
477 	for (int i = 0; i < 4; i++)
478 		if (readMantissaBits[i] >= srcMantissaBits[i])
479 			ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i];
480 
481 	return UVec4(4) * (UVec4(1) << (ULPDiff.cast<deUint32>()));
482 }
483 
verifyRenderbuffer(TestLog & log,tcu::ResultCollector & results,const tcu::TextureFormat & format,int renderbufferNdx,const tcu::TextureLevel & refRenderbuffer,const tcu::TextureLevel & result)484 void verifyRenderbuffer (TestLog&					log,
485 						 tcu::ResultCollector&		results,
486 						 const tcu::TextureFormat&	format,
487 						 int						renderbufferNdx,
488 						 const tcu::TextureLevel&	refRenderbuffer,
489 						 const tcu::TextureLevel&	result)
490 {
491 	switch (tcu::getTextureChannelClass(format.type))
492 	{
493 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
494 		{
495 			const string	name		= "Renderbuffer" + de::toString(renderbufferNdx);
496 			const string	desc		= "Compare renderbuffer " + de::toString(renderbufferNdx);
497 			const UVec4		threshold	= getFloatULPThreshold(format, result.getFormat());
498 
499 			if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
500 				results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
501 
502 			break;
503 		}
504 
505 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
506 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
507 		{
508 			const string	name		= "Renderbuffer" + de::toString(renderbufferNdx);
509 			const string	desc		= "Compare renderbuffer " + de::toString(renderbufferNdx);
510 			const UVec4		threshold	(1, 1, 1, 1);
511 
512 			if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
513 				results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
514 
515 			break;
516 		}
517 
518 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
519 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
520 		{
521 			const string	name		= "Renderbuffer" + de::toString(renderbufferNdx);
522 			const string	desc		= "Compare renderbuffer " + de::toString(renderbufferNdx);
523 			const Vec4		threshold	= getFixedPointFormatThreshold(format, result.getFormat());
524 
525 			if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT))
526 				results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed.");
527 
528 			break;
529 		}
530 
531 		default:
532 			DE_ASSERT(DE_FALSE);
533 	}
534 }
535 
getReadPixelFormat(const TextureFormat & format)536 TextureFormat getReadPixelFormat (const TextureFormat& format)
537 {
538 	switch (tcu::getTextureChannelClass(format.type))
539 	{
540 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
541 			return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32);
542 
543 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
544 			return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32);
545 
546 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
547 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
548 			return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
549 
550 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
551 			return TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT);
552 
553 		default:
554 			DE_ASSERT(false);
555 			return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
556 	}
557 }
558 
verifyRenderbuffers(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const glu::RenderbufferVector & renderbuffers,const glu::Framebuffer & framebuffer,const vector<TextureLevel> & refRenderbuffers)559 void verifyRenderbuffers (TestLog&							log,
560 							tcu::ResultCollector&				results,
561 							glu::RenderContext&				renderContext,
562 							const glu::RenderbufferVector&	renderbuffers,
563 							const glu::Framebuffer&			framebuffer,
564 							const vector<TextureLevel>&		refRenderbuffers)
565 {
566 	const glw::Functions& gl = renderContext.getFunctions();
567 
568 	DE_ASSERT(renderbuffers.size() == refRenderbuffers.size());
569 
570 	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
571 
572 	for (int renderbufferNdx = 0; renderbufferNdx < (int)renderbuffers.size(); renderbufferNdx++)
573 	{
574 		const TextureLevel&	refRenderbuffer	= refRenderbuffers[renderbufferNdx];
575 		const int			width			= refRenderbuffer.getWidth();
576 		const int			height			= refRenderbuffer.getHeight();
577 		const TextureFormat	format			= refRenderbuffer.getFormat();
578 
579 		tcu::TextureLevel	result			(getReadPixelFormat(format), width, height);
580 
581 		gl.readBuffer(GL_COLOR_ATTACHMENT0 + renderbufferNdx);
582 		glu::readPixels(renderContext, 0, 0, result.getAccess());
583 		GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels from renderbuffer failed.");
584 
585 		verifyRenderbuffer(log, results, format, renderbufferNdx, refRenderbuffer, result);
586 	}
587 
588 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
589 }
590 
591 static const float s_quadCoords[] =
592 {
593 	-0.5f, -0.5f,
594 	 0.5f, -0.5f,
595 	 0.5f,  0.5f,
596 
597 	 0.5f,  0.5f,
598 	-0.5f,  0.5f,
599 	-0.5f, -0.5f
600 };
601 
setBlendState(rr::FragmentOperationState & fragOps,const BlendState & state)602 void setBlendState (rr::FragmentOperationState& fragOps, const BlendState& state)
603 {
604 	if (state.blendEq)
605 	{
606 		if (state.blendEq->is<BlendEq>())
607 		{
608 			if (isAdvancedBlendEq(state.blendEq->get<BlendEq>()))
609 			{
610 				const rr::BlendEquationAdvanced	equation = mapGLBlendEquationAdvanced(state.blendEq->get<BlendEq>());
611 
612 				fragOps.blendMode				= rr::BLENDMODE_ADVANCED;
613 				fragOps.blendEquationAdvaced	= equation;
614 			}
615 			else
616 			{
617 				const rr::BlendEquation equation = mapGLBlendEquation(state.blendEq->get<BlendEq>());
618 
619 				fragOps.blendMode				= rr::BLENDMODE_STANDARD;
620 				fragOps.blendRGBState.equation	= equation;
621 				fragOps.blendAState.equation	= equation;
622 			}
623 		}
624 		else
625 		{
626 			DE_ASSERT(state.blendEq->is<SeparateBlendEq>());
627 
628 			fragOps.blendMode				= rr::BLENDMODE_STANDARD;
629 			fragOps.blendRGBState.equation	= mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().rgb);
630 			fragOps.blendAState.equation	= mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().alpha);
631 		}
632 	}
633 
634 	if (state.blendFunc)
635 	{
636 		if (state.blendFunc->is<BlendFunc>())
637 		{
638 			const rr::BlendFunc srcFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().src);
639 			const rr::BlendFunc dstFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().dst);
640 
641 			fragOps.blendRGBState.srcFunc	= srcFunction;
642 			fragOps.blendRGBState.dstFunc	= dstFunction;
643 
644 			fragOps.blendAState.srcFunc		= srcFunction;
645 			fragOps.blendAState.dstFunc		= dstFunction;
646 		}
647 		else
648 		{
649 			DE_ASSERT(state.blendFunc->is<SeparateBlendFunc>());
650 
651 			fragOps.blendRGBState.srcFunc	= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.src);
652 			fragOps.blendRGBState.dstFunc	= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.dst);
653 
654 			fragOps.blendAState.srcFunc		= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.src);
655 			fragOps.blendAState.dstFunc		= mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.dst);
656 		}
657 	}
658 
659 	if (state.colorMask)
660 		fragOps.colorMask = *state.colorMask;
661 }
662 
createRenderState(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const DrawBufferInfo & info,int subpixelBits)663 rr::RenderState createRenderState (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const DrawBufferInfo& info, int subpixelBits)
664 {
665 	const IVec2		size	= info.getSize();
666 	rr::RenderState	state	(rr::ViewportState(rr::WindowRectangle(0, 0, size.x(), size.y())), subpixelBits);
667 
668 	state.fragOps.blendMode = rr::BLENDMODE_STANDARD;
669 
670 	setBlendState(state.fragOps, preCommonBlendState);
671 	setBlendState(state.fragOps, info.getBlendState());
672 	setBlendState(state.fragOps, postCommonBlendState);
673 
674 	if (postCommonBlendState.enableBlend)
675 		state.fragOps.blendMode = (*(postCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
676 	else  if (info.getBlendState().enableBlend)
677 		state.fragOps.blendMode = (*(info.getBlendState().enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
678 	else if (preCommonBlendState.enableBlend)
679 		state.fragOps.blendMode = (*(preCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE);
680 	else
681 		state.fragOps.blendMode = rr::BLENDMODE_NONE;
682 
683 	if (tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
684 		&& tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
685 		&& tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
686 		state.fragOps.blendMode = rr::BLENDMODE_NONE;
687 
688 	return state;
689 }
690 
691 class VertexShader : public rr::VertexShader
692 {
693 public:
694 					VertexShader	(void);
695 	virtual void	shadeVertices	(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
696 };
697 
VertexShader(void)698 VertexShader::VertexShader (void)
699 	: rr::VertexShader	(1, 1)
700 {
701 	m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
702 	m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
703 }
704 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const705 void VertexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
706 {
707 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
708 	{
709 		rr::VertexPacket& packet = *packets[packetNdx];
710 
711 		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
712 		packet.outputs[0]	= 0.5f * (Vec4(1.0f) + rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx));
713 	}
714 }
715 
716 class FragmentShader : public rr::FragmentShader
717 {
718 public:
719 			FragmentShader	(int drawBufferNdx, const DrawBufferInfo& info);
720 	void	shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
721 
722 private:
723 	const int				m_drawBufferNdx;
724 	const DrawBufferInfo	m_info;
725 };
726 
FragmentShader(int drawBufferNdx,const DrawBufferInfo & info)727 FragmentShader::FragmentShader (int drawBufferNdx, const DrawBufferInfo& info)
728 	: rr::FragmentShader	(1, 1)
729 	, m_drawBufferNdx		(drawBufferNdx)
730 	, m_info				(info)
731 {
732 	m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
733 
734 	switch (tcu::getTextureChannelClass(m_info.getFormat().type))
735 	{
736 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
737 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
738 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
739 			m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
740 			break;
741 
742 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
743 			m_outputs[0].type = rr::GENERICVECTYPE_UINT32;
744 			break;
745 
746 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
747 			m_outputs[0].type = rr::GENERICVECTYPE_INT32;
748 			break;
749 
750 		default:
751 			DE_ASSERT(false);
752 	}
753 }
754 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const755 void FragmentShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
756 {
757 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
758 	{
759 		rr::FragmentPacket& packet = packets[packetNdx];
760 
761 		DE_ASSERT(m_drawBufferNdx >= 0);
762 		DE_UNREF(m_info);
763 
764 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
765 		{
766 			const Vec2	vColor		= rr::readVarying<float>(packet, context, 0, fragNdx).xy();
767 			const float	values[]	=
768 			{
769 				vColor.x(),
770 				vColor.y(),
771 				(1.0f - vColor.x()),
772 				(1.0f - vColor.y())
773 			};
774 
775 			switch (tcu::getTextureChannelClass(m_info.getFormat().type))
776 			{
777 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
778 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
779 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
780 				{
781 					const Vec4 color (values[(m_drawBufferNdx + 0) % 4],
782 									  values[(m_drawBufferNdx + 1) % 4],
783 									  values[(m_drawBufferNdx + 2) % 4],
784 									  values[(m_drawBufferNdx + 3) % 4]);
785 
786 					rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
787 					break;
788 				}
789 
790 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
791 				{
792 					const UVec4 color ((deUint32)(values[(m_drawBufferNdx + 0) % 4]),
793 									   (deUint32)(values[(m_drawBufferNdx + 1) % 4]),
794 									   (deUint32)(values[(m_drawBufferNdx + 2) % 4]),
795 									   (deUint32)(values[(m_drawBufferNdx + 3) % 4]));
796 
797 					rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
798 					break;
799 				}
800 
801 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
802 				{
803 					const IVec4 color ((deInt32)(values[(m_drawBufferNdx + 0) % 4]),
804 									   (deInt32)(values[(m_drawBufferNdx + 1) % 4]),
805 									   (deInt32)(values[(m_drawBufferNdx + 2) % 4]),
806 									   (deInt32)(values[(m_drawBufferNdx + 3) % 4]));
807 
808 					rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
809 					break;
810 				}
811 
812 				default:
813 					DE_ASSERT(DE_FALSE);
814 			}
815 		}
816 	}
817 }
818 
createVertexAttrib(const float * coords)819 rr::VertexAttrib createVertexAttrib (const float* coords)
820 {
821 	rr::VertexAttrib attrib;
822 
823 	attrib.type		= rr::VERTEXATTRIBTYPE_FLOAT;
824 	attrib.size		= 2;
825 	attrib.pointer	= coords;
826 
827 	return attrib;
828 }
829 
renderRefQuad(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const int subpixelBits,vector<TextureLevel> & refRenderbuffers)830 void renderRefQuad (const BlendState&				preCommonBlendState,
831 					const BlendState&				postCommonBlendState,
832 					const vector<DrawBufferInfo>&	drawBuffers,
833 					const int						subpixelBits,
834 					vector<TextureLevel>&			refRenderbuffers)
835 {
836 	const rr::Renderer			renderer;
837 	const rr::PrimitiveList		primitives		(rr::PRIMITIVETYPE_TRIANGLES, 6, 0);
838 	const rr::VertexAttrib		vertexAttribs[] =
839 	{
840 		createVertexAttrib(s_quadCoords)
841 	};
842 
843 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
844 	{
845 		if (drawBuffers[drawBufferNdx].getRender())
846 		{
847 			const rr::RenderState	renderState		(createRenderState(preCommonBlendState, postCommonBlendState, drawBuffers[drawBufferNdx], subpixelBits));
848 			const rr::RenderTarget	renderTarget	(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refRenderbuffers[drawBufferNdx].getAccess()));
849 			const VertexShader		vertexShader;
850 			const FragmentShader	fragmentShader	(drawBufferNdx, drawBuffers[drawBufferNdx]);
851 			const rr::Program		program			(&vertexShader, &fragmentShader);
852 			const rr::DrawCommand	command			(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, primitives);
853 
854 			renderer.draw(command);
855 		}
856 	}
857 }
858 
requiresAdvancedBlendEq(const BlendState & pre,const BlendState post,const vector<DrawBufferInfo> & drawBuffers)859 bool requiresAdvancedBlendEq (const BlendState& pre, const BlendState post, const vector<DrawBufferInfo>& drawBuffers)
860 {
861 	bool requiresAdvancedBlendEq = false;
862 
863 	if (pre.blendEq && pre.blendEq->is<BlendEq>())
864 		requiresAdvancedBlendEq |= isAdvancedBlendEq(pre.blendEq->get<BlendEq>());
865 
866 	if (post.blendEq && post.blendEq->is<BlendEq>())
867 		requiresAdvancedBlendEq |= isAdvancedBlendEq(post.blendEq->get<BlendEq>());
868 
869 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
870 	{
871 		const BlendState& drawBufferBlendState = drawBuffers[drawBufferNdx].getBlendState();
872 
873 		if (drawBufferBlendState.blendEq && drawBufferBlendState.blendEq->is<BlendEq>())
874 			requiresAdvancedBlendEq |= isAdvancedBlendEq(drawBufferBlendState.blendEq->get<BlendEq>());
875 	}
876 
877 	return requiresAdvancedBlendEq;
878 }
879 
genVertexSource(glu::RenderContext & renderContext)880 glu::VertexSource genVertexSource (glu::RenderContext& renderContext)
881 {
882 	const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
883 
884 	const char* const vertexSource =
885 		"${GLSL_VERSION_DECL}\n"
886 		"layout(location=0) in highp vec2 i_coord;\n"
887 		"out highp vec2 v_color;\n"
888 		"void main (void)\n"
889 		"{\n"
890 		"\tv_color = 0.5 * (vec2(1.0) + i_coord);\n"
891 		"\tgl_Position = vec4(i_coord, 0.0, 1.0);\n"
892 		"}";
893 
894 	map<string, string> args;
895 	args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_300_ES);
896 
897 	return glu::VertexSource(tcu::StringTemplate(vertexSource).specialize(args));
898 }
899 
genFragmentSource(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,glu::RenderContext & renderContext)900 glu::FragmentSource genFragmentSource (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
901 {
902 	std::ostringstream stream;
903 	const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
904 
905 	stream << "${GLSL_VERSION_DECL}\n";
906 
907 	if (requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers))
908 	{
909 		stream << "${GLSL_EXTENSION}"
910 			   <<  "layout(blend_support_all_equations) out;\n";
911 	}
912 
913 	stream << "in highp vec2 v_color;\n";
914 
915 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
916 	{
917 		const DrawBufferInfo&	drawBuffer			= drawBuffers[drawBufferNdx];
918 		const TextureFormat&	format				= drawBuffer.getFormat();
919 
920 		stream << "layout(location=" << drawBufferNdx << ") out highp ";
921 
922 		switch (tcu::getTextureChannelClass(format.type))
923 		{
924 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
925 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
926 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
927 				stream << "vec4";
928 				break;
929 
930 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
931 				stream << "uvec4";
932 				break;
933 
934 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
935 				stream << "ivec4";
936 				break;
937 
938 			default:
939 				DE_ASSERT(DE_FALSE);
940 		}
941 
942 		stream << " o_drawBuffer" <<  drawBufferNdx << ";\n";
943 	}
944 
945 	stream << "void main (void)\n"
946 		   << "{\n";
947 
948 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
949 	{
950 		const DrawBufferInfo&	drawBuffer		= drawBuffers[drawBufferNdx];
951 		const TextureFormat&	format			= drawBuffer.getFormat();
952 		const char* const		values[]		=
953 		{
954 			"v_color.x",
955 			"v_color.y",
956 			"(1.0 - v_color.x)",
957 			"(1.0 - v_color.y)"
958 		};
959 
960 		stream << "\to_drawBuffer" <<  drawBufferNdx;
961 
962 		switch (tcu::getTextureChannelClass(format.type))
963 		{
964 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
965 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
966 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
967 				stream << " = vec4(" << values[(drawBufferNdx + 0) % 4]
968 					   << ", " << values[(drawBufferNdx + 1) % 4]
969 					   << ", " << values[(drawBufferNdx + 2) % 4]
970 					   << ", " << values[(drawBufferNdx + 3) % 4] << ");\n";
971 				break;
972 
973 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
974 				stream << " = uvec4(uint(" << values[(drawBufferNdx + 0) % 4]
975 					   << "), uint(" << values[(drawBufferNdx + 1) % 4]
976 					   << "), uint(" << values[(drawBufferNdx + 2) % 4]
977 					   << "), uint(" << values[(drawBufferNdx + 3) % 4] << "));\n";
978 				break;
979 
980 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
981 				stream << " = ivec4(int(" << values[(drawBufferNdx + 0) % 4]
982 					   << "), int(" << values[(drawBufferNdx + 1) % 4]
983 					   << "), int(" << values[(drawBufferNdx + 2) % 4]
984 					   << "), int(" << values[(drawBufferNdx + 3) % 4] << "));\n";
985 				break;
986 
987 			default:
988 				DE_ASSERT(DE_FALSE);
989 		}
990 	}
991 
992 	stream << "}";
993 
994 	map<string, string> args;
995 	args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_300_ES);
996 	args["GLSL_EXTENSION"] = supportsES32 ? "\n" : "#extension GL_KHR_blend_equation_advanced : require\n";
997 
998 	return glu::FragmentSource(tcu::StringTemplate(stream.str()).specialize(args));
999 }
1000 
genShaderSources(const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,glu::RenderContext & renderContext)1001 glu::ProgramSources genShaderSources (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext)
1002 {
1003 	return glu::ProgramSources() << genVertexSource(renderContext) << genFragmentSource(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext);
1004 }
1005 
renderGLQuad(glu::RenderContext & renderContext,const glu::ShaderProgram & program)1006 void renderGLQuad (glu::RenderContext&			renderContext,
1007 				   const glu::ShaderProgram&	program)
1008 {
1009 	const glu::VertexArrayBinding vertexArrays[] =
1010 	{
1011 		glu::VertexArrayBinding(glu::BindingPoint(0), glu::VertexArrayPointer(glu::VTX_COMP_FLOAT, glu::VTX_COMP_CONVERT_NONE, 2, 6, 0, s_quadCoords))
1012 	};
1013 
1014 	glu::draw(renderContext, program.getProgram(), 1, vertexArrays, glu::pr::Triangles(6));
1015 }
1016 
renderQuad(TestLog & log,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const glu::Framebuffer & framebuffer,vector<TextureLevel> & refRenderbuffers)1017 void renderQuad (TestLog&						log,
1018 				 glu::RenderContext&			renderContext,
1019 				 const BlendState&				preCommonBlendState,
1020 				 const BlendState&				postCommonBlendState,
1021 				 const vector<DrawBufferInfo>&	drawBuffers,
1022 				 const glu::Framebuffer&		framebuffer,
1023 				 vector<TextureLevel>&			refRenderbuffers)
1024 {
1025 	const glw::Functions&		gl						= renderContext.getFunctions();
1026 	const glu::ShaderProgram	program					(gl, genShaderSources(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext));
1027 	const IVec2					size					= drawBuffers[0].getSize();
1028 	const bool					requiresBlendBarriers	= requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers);
1029 
1030 	vector<deUint32> bufs;
1031 
1032 	bufs.resize(drawBuffers.size());
1033 
1034 	for (int bufNdx = 0; bufNdx < (int)bufs.size(); bufNdx++)
1035 		bufs[bufNdx] = (drawBuffers[bufNdx].getRender() ? GL_COLOR_ATTACHMENT0 + bufNdx : GL_NONE);
1036 
1037 	log << program;
1038 
1039 	gl.viewport(0, 0, size.x(), size.y());
1040 	gl.useProgram(program.getProgram());
1041 	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
1042 
1043 	setCommonBlendState(gl, preCommonBlendState);
1044 
1045 	for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++)
1046 		setIndexedBlendState(gl, drawBuffers[renderbufferNdx].getBlendState(), renderbufferNdx);
1047 
1048 	setCommonBlendState(gl, postCommonBlendState);
1049 
1050 	gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0]));
1051 
1052 	if (requiresBlendBarriers)
1053 		gl.blendBarrier();
1054 
1055 	renderGLQuad(renderContext, program);
1056 
1057 	if (requiresBlendBarriers)
1058 		gl.blendBarrier();
1059 
1060 	gl.drawBuffers(0, 0);
1061 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1062 	gl.useProgram(0);
1063 
1064 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
1065 
1066 	int subpixelBits = 0;
1067 	gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
1068 
1069 	renderRefQuad(preCommonBlendState, postCommonBlendState, drawBuffers, subpixelBits, refRenderbuffers);
1070 }
1071 
logBlendState(TestLog & log,const BlendState & blend)1072 void logBlendState (TestLog&			log,
1073 					const BlendState&	blend)
1074 {
1075 	if (blend.enableBlend)
1076 	{
1077 		if (*blend.enableBlend)
1078 			log << TestLog::Message << "Enable blending." << TestLog::EndMessage;
1079 		else
1080 			log << TestLog::Message << "Disable blending." << TestLog::EndMessage;
1081 	}
1082 
1083 	if (blend.colorMask)
1084 	{
1085 		const BVec4 mask = *blend.colorMask;
1086 
1087 		log << TestLog::Message << "Set color mask: " << mask << "." << TestLog::EndMessage;
1088 	}
1089 
1090 	if (blend.blendEq)
1091 	{
1092 		const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq;
1093 
1094 		if (blendEq.is<BlendEq>())
1095 			log << TestLog::Message << "Set blend equation: " << glu::getBlendEquationStr(blendEq.get<BlendEq>()) << "." << TestLog::EndMessage;
1096 		else if (blendEq.is<SeparateBlendEq>())
1097 			log << TestLog::Message << "Set blend equation rgb: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().rgb) << ", alpha: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().alpha) << "." << TestLog::EndMessage;
1098 		else
1099 			DE_ASSERT(false);
1100 	}
1101 
1102 	if (blend.blendFunc)
1103 	{
1104 		const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc;
1105 
1106 		if (blendFunc.is<BlendFunc>())
1107 			log << TestLog::Message << "Set blend function source: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().dst) << "." << TestLog::EndMessage;
1108 		else if (blendFunc.is<SeparateBlendFunc>())
1109 		{
1110 			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;
1111 			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;
1112 		}
1113 		else
1114 			DE_ASSERT(false);
1115 	}
1116 }
1117 
logTestCaseInfo(TestLog & log,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)1118 void logTestCaseInfo (TestLog&						log,
1119 					  const BlendState&				preCommonBlendState,
1120 					  const BlendState&				postCommonBlendState,
1121 					  const vector<DrawBufferInfo>&	drawBuffers)
1122 {
1123 	{
1124 		tcu::ScopedLogSection drawBuffersSection(log, "DrawBuffers", "Draw buffers");
1125 
1126 		for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
1127 		{
1128 			const tcu::ScopedLogSection	drawBufferSection	(log, "DrawBuffer" + de::toString(drawBufferNdx), "Draw Buffer " + de::toString(drawBufferNdx));
1129 			const DrawBufferInfo&		drawBuffer			= drawBuffers[drawBufferNdx];
1130 
1131 			log << TestLog::Message << "Format: " << drawBuffer.getFormat() << TestLog::EndMessage;
1132 			log << TestLog::Message << "Size: " << drawBuffer.getSize() << TestLog::EndMessage;
1133 			log << TestLog::Message << "Render: " << (drawBuffer.getRender() ? "true" : "false") << TestLog::EndMessage;
1134 		}
1135 	}
1136 
1137 	if (!preCommonBlendState.isEmpty())
1138 	{
1139 		tcu::ScopedLogSection s(log, "PreCommonState", "First set common blend state");
1140 		logBlendState(log, preCommonBlendState);
1141 	}
1142 
1143 	for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++)
1144 	{
1145 		if (!drawBuffers[drawBufferNdx].getBlendState().isEmpty())
1146 		{
1147 			const tcu::ScopedLogSection s(log, "DrawBufferState" + de::toString(drawBufferNdx), "Set DrawBuffer " + de::toString(drawBufferNdx) + " state to");
1148 
1149 			logBlendState(log, drawBuffers[drawBufferNdx].getBlendState());
1150 		}
1151 	}
1152 
1153 	if (!postCommonBlendState.isEmpty())
1154 	{
1155 		tcu::ScopedLogSection s(log, "PostCommonState", "After set common blend state");
1156 		logBlendState(log, postCommonBlendState);
1157 	}
1158 }
1159 
runTest(TestLog & log,tcu::ResultCollector & results,glu::RenderContext & renderContext,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers)1160 void runTest (TestLog&						log,
1161 			  tcu::ResultCollector&			results,
1162 			  glu::RenderContext&			renderContext,
1163 
1164 			  const BlendState&				preCommonBlendState,
1165 			  const BlendState&				postCommonBlendState,
1166 			  const vector<DrawBufferInfo>&	drawBuffers)
1167 {
1168 	const glw::Functions&	gl					= renderContext.getFunctions();
1169 	glu::RenderbufferVector	renderbuffers		(gl, drawBuffers.size());
1170 	glu::Framebuffer		framebuffer			(gl);
1171 	vector<TextureLevel>	refRenderbuffers	(drawBuffers.size());
1172 
1173 	logTestCaseInfo(log, preCommonBlendState, postCommonBlendState, drawBuffers);
1174 
1175 	genRenderbuffers(gl, drawBuffers, framebuffer, renderbuffers, refRenderbuffers);
1176 
1177 	renderQuad(log, renderContext, preCommonBlendState, postCommonBlendState, drawBuffers, framebuffer, refRenderbuffers);
1178 
1179 	verifyRenderbuffers(log, results, renderContext, renderbuffers, framebuffer, refRenderbuffers);
1180 }
1181 
1182 class DrawBuffersIndexedTest : public TestCase
1183 {
1184 public:
1185 					DrawBuffersIndexedTest (Context&						context,
1186 											const BlendState&				preCommonBlendState,
1187 											const BlendState&				postCommonBlendState,
1188 											const vector<DrawBufferInfo>&	drawBuffers,
1189 											const string&					name,
1190 											const string&					description);
1191 
1192 	void			init					(void);
1193 	IterateResult	iterate					(void);
1194 
1195 private:
1196 	const BlendState				m_preCommonBlendState;
1197 	const BlendState				m_postCommonBlendState;
1198 	const vector<DrawBufferInfo>	m_drawBuffers;
1199 };
1200 
DrawBuffersIndexedTest(Context & context,const BlendState & preCommonBlendState,const BlendState & postCommonBlendState,const vector<DrawBufferInfo> & drawBuffers,const string & name,const string & description)1201 DrawBuffersIndexedTest::DrawBuffersIndexedTest (Context&						context,
1202 												const BlendState&				preCommonBlendState,
1203 												const BlendState&				postCommonBlendState,
1204 												const vector<DrawBufferInfo>&	drawBuffers,
1205 												const string&					name,
1206 												const string&					description)
1207 	: TestCase					(context, name.c_str(), description.c_str())
1208 	, m_preCommonBlendState		(preCommonBlendState)
1209 	, m_postCommonBlendState	(postCommonBlendState)
1210 	, m_drawBuffers				(drawBuffers)
1211 {
1212 }
1213 
init(void)1214 void DrawBuffersIndexedTest::init (void)
1215 {
1216 	const bool supportsES32orGL45 = checkES32orGL45Support(m_context);
1217 
1218 	if (!supportsES32orGL45)
1219 	{
1220 		if (requiresAdvancedBlendEq(m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers) && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
1221 			TCU_THROW(NotSupportedError, "Extension GL_KHR_blend_equation_advanced not supported");
1222 
1223 		if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1224 			TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1225 	}
1226 }
1227 
iterate(void)1228 TestCase::IterateResult DrawBuffersIndexedTest::iterate (void)
1229 {
1230 	TestLog&				log		= m_testCtx.getLog();
1231 	tcu::ResultCollector	results	(log);
1232 
1233 	runTest(log, results, m_context.getRenderContext(), m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers);
1234 
1235 	results.setTestContextResult(m_testCtx);
1236 
1237 	return STOP;
1238 }
1239 
getRandomBlendEq(de::Random & rng)1240 BlendEq getRandomBlendEq (de::Random& rng)
1241 {
1242 	const BlendEq eqs[] =
1243 	{
1244 		GL_FUNC_ADD,
1245 		GL_FUNC_SUBTRACT,
1246 		GL_FUNC_REVERSE_SUBTRACT,
1247 		GL_MIN,
1248 		GL_MAX
1249 	};
1250 
1251 	return de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(eqs)>(eqs, rng.getUint32() % DE_LENGTH_OF_ARRAY(eqs));
1252 }
1253 
getRandomBlendFunc(de::Random & rng)1254 BlendFunc getRandomBlendFunc (de::Random& rng)
1255 {
1256 	const deUint32 funcs[] =
1257 	{
1258 		GL_ZERO,
1259 		GL_ONE,
1260 		GL_SRC_COLOR,
1261 		GL_ONE_MINUS_SRC_COLOR,
1262 		GL_DST_COLOR,
1263 		GL_ONE_MINUS_DST_COLOR,
1264 		GL_SRC_ALPHA,
1265 		GL_ONE_MINUS_SRC_ALPHA,
1266 		GL_DST_ALPHA,
1267 		GL_ONE_MINUS_DST_ALPHA,
1268 		GL_CONSTANT_COLOR,
1269 		GL_ONE_MINUS_CONSTANT_COLOR,
1270 		GL_CONSTANT_ALPHA,
1271 		GL_ONE_MINUS_CONSTANT_ALPHA,
1272 		GL_SRC_ALPHA_SATURATE
1273 	};
1274 
1275 	const deUint32 src = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
1276 	const deUint32 dst = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs));
1277 
1278 	return BlendFunc(src, dst);
1279 }
1280 
genRandomBlendState(de::Random & rng,BlendState & blendState)1281 void genRandomBlendState (de::Random& rng, BlendState& blendState)
1282 {
1283 	if (rng.getBool())
1284 		blendState.enableBlend = rng.getBool();
1285 
1286 	if (rng.getBool())
1287 	{
1288 		if (rng.getBool())
1289 			blendState.blendEq = getRandomBlendEq(rng);
1290 		else
1291 		{
1292 			const BlendEq	rgb		= getRandomBlendEq(rng);
1293 			const BlendEq	alpha	= getRandomBlendEq(rng);
1294 
1295 			blendState.blendEq		= SeparateBlendEq(rgb, alpha);
1296 		}
1297 	}
1298 
1299 	if (rng.getBool())
1300 	{
1301 		if (rng.getBool())
1302 			blendState.blendFunc = getRandomBlendFunc(rng);
1303 		else
1304 		{
1305 			const BlendFunc	rgb		= getRandomBlendFunc(rng);
1306 			const BlendFunc	alpha	= getRandomBlendFunc(rng);
1307 
1308 			blendState.blendFunc	= SeparateBlendFunc(rgb, alpha);
1309 		}
1310 	}
1311 
1312 	if (rng.getBool())
1313 	{
1314 		const bool red		= rng.getBool();
1315 		const bool green	= rng.getBool();
1316 		const bool blue		= rng.getBool();
1317 		const bool alpha	= rng.getBool();
1318 
1319 		blendState.colorMask = BVec4(red, blue, green, alpha);
1320 	}
1321 }
1322 
getRandomFormat(de::Random & rng,Context & context)1323 TextureFormat getRandomFormat (de::Random& rng, Context& context)
1324 {
1325 	const bool supportsES32orGL45 = checkES32orGL45Support(context);
1326 
1327 	const deUint32 glFormats[] =
1328 	{
1329 		GL_R8,
1330 		GL_RG8,
1331 		GL_RGB8,
1332 		GL_RGB565,
1333 		GL_RGBA4,
1334 		GL_RGB5_A1,
1335 		GL_RGBA8,
1336 		GL_RGB10_A2,
1337 		GL_RGB10_A2UI,
1338 		GL_R8I,
1339 		GL_R8UI,
1340 		GL_R16I,
1341 		GL_R16UI,
1342 		GL_R32I,
1343 		GL_R32UI,
1344 		GL_RG8I,
1345 		GL_RG8UI,
1346 		GL_RG16I,
1347 		GL_RG16UI,
1348 		GL_RG32I,
1349 		GL_RG32UI,
1350 		GL_RGBA8I,
1351 		GL_RGBA8UI,
1352 		GL_RGBA16I,
1353 		GL_RGBA16UI,
1354 		GL_RGBA32I,
1355 		GL_RGBA32UI,
1356 		GL_RGBA16F,
1357 		GL_R32F,
1358 		GL_RG32F,
1359 		GL_RGBA32F,
1360 		GL_R11F_G11F_B10F
1361 	};
1362 
1363 	if (supportsES32orGL45)
1364 		return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % DE_LENGTH_OF_ARRAY(glFormats)));
1365 	else
1366 	{
1367 		DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(glFormats) == 32);
1368 		return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % (DE_LENGTH_OF_ARRAY(glFormats) - 5)));
1369 	}
1370 }
1371 
genRandomTest(de::Random & rng,BlendState & preCommon,BlendState & postCommon,vector<DrawBufferInfo> & drawBuffers,int maxDrawBufferCount,Context & context)1372 void genRandomTest (de::Random& rng, BlendState& preCommon, BlendState& postCommon, vector<DrawBufferInfo>& drawBuffers, int maxDrawBufferCount, Context& context)
1373 {
1374 	genRandomBlendState(rng, preCommon);
1375 	genRandomBlendState(rng, postCommon);
1376 
1377 	for (int drawBufferNdx = 0; drawBufferNdx < maxDrawBufferCount; drawBufferNdx++)
1378 	{
1379 		const bool			render		= rng.getFloat() > 0.1f;
1380 		const IVec2			size		(64, 64);
1381 		const TextureFormat	format		(getRandomFormat(rng, context));
1382 		BlendState			blendState;
1383 
1384 		genRandomBlendState(rng, blendState);
1385 
1386 		// 32bit float formats don't support blending in GLES32
1387 		if (format.type == tcu::TextureFormat::FLOAT)
1388 		{
1389 			// If format is 32bit float post common can't enable blending
1390 			if (postCommon.enableBlend && *postCommon.enableBlend)
1391 			{
1392 				// Either don't set enable blend or disable blending
1393 				if (rng.getBool())
1394 					postCommon.enableBlend = tcu::Nothing;
1395 				else
1396 					postCommon.enableBlend = tcu::just(false);
1397 			}
1398 
1399 			// If post common doesn't disable blending, per attachment state or
1400 			// pre common must.
1401 			if (!postCommon.enableBlend)
1402 			{
1403 				// If pre common enables blend per attachment must disable it
1404 				// If per attachment state changes blend state it must disable it
1405 				if ((preCommon.enableBlend && *preCommon.enableBlend)
1406 					|| blendState.enableBlend)
1407 					blendState.enableBlend = tcu::just(false);
1408 			}
1409 		}
1410 
1411 		drawBuffers.push_back(DrawBufferInfo(render, size, blendState, format));
1412 	}
1413 }
1414 
1415 class MaxDrawBuffersIndexedTest : public TestCase
1416 {
1417 public:
1418 					MaxDrawBuffersIndexedTest	(Context& contet, int seed);
1419 
1420 	void			init						(void);
1421 	IterateResult	iterate						(void);
1422 
1423 private:
1424 	const int		m_seed;
1425 };
1426 
MaxDrawBuffersIndexedTest(Context & context,int seed)1427 MaxDrawBuffersIndexedTest::MaxDrawBuffersIndexedTest (Context& context, int seed)
1428 	: TestCase	(context, de::toString(seed).c_str(), de::toString(seed).c_str())
1429 	, m_seed	(deInt32Hash(seed) ^ 1558001307u)
1430 {
1431 }
1432 
init(void)1433 void MaxDrawBuffersIndexedTest::init (void)
1434 {
1435 	const bool supportsES32orGL45 = checkES32orGL45Support(m_context);
1436 
1437 	if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1438 		TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1439 }
1440 
iterate(void)1441 TestCase::IterateResult MaxDrawBuffersIndexedTest::iterate (void)
1442 {
1443 	TestLog&				log						= m_testCtx.getLog();
1444 	tcu::ResultCollector	results					(log);
1445 	de::Random				rng						(m_seed);
1446 	BlendState				preCommonBlendState;
1447 	BlendState				postCommonBlendState;
1448 	vector<DrawBufferInfo>	drawBuffers;
1449 
1450 	genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, 4, m_context);
1451 
1452 	runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
1453 
1454 	results.setTestContextResult(m_testCtx);
1455 
1456 	return STOP;
1457 }
1458 
1459 class ImplMaxDrawBuffersIndexedTest : public TestCase
1460 {
1461 public:
1462 					ImplMaxDrawBuffersIndexedTest	(Context& contet, int seed);
1463 
1464 	void			init							(void);
1465 	IterateResult	iterate							(void);
1466 
1467 private:
1468 	const int		m_seed;
1469 };
1470 
ImplMaxDrawBuffersIndexedTest(Context & context,int seed)1471 ImplMaxDrawBuffersIndexedTest::ImplMaxDrawBuffersIndexedTest (Context& context, int seed)
1472 	: TestCase	(context, de::toString(seed).c_str(), de::toString(seed).c_str())
1473 	, m_seed	(deInt32Hash(seed) ^ 2686315738u)
1474 {
1475 }
1476 
init(void)1477 void ImplMaxDrawBuffersIndexedTest::init (void)
1478 {
1479 	const bool supportsES32orGL45 = checkES32orGL45Support(m_context);
1480 
1481 	if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"))
1482 		TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported");
1483 }
1484 
iterate(void)1485 TestCase::IterateResult ImplMaxDrawBuffersIndexedTest::iterate (void)
1486 {
1487 	TestLog&				log						= m_testCtx.getLog();
1488 	tcu::ResultCollector	results					(log);
1489 	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
1490 	de::Random				rng						(m_seed);
1491 	deInt32					maxDrawBuffers			= 0;
1492 	BlendState				preCommonBlendState;
1493 	BlendState				postCommonBlendState;
1494 	vector<DrawBufferInfo>	drawBuffers;
1495 
1496 	gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1497 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_DRAW_BUFFERS) failed");
1498 
1499 	TCU_CHECK(maxDrawBuffers > 0);
1500 
1501 	genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, maxDrawBuffers, m_context);
1502 
1503 	runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers);
1504 
1505 	results.setTestContextResult(m_testCtx);
1506 
1507 	return STOP;
1508 }
1509 
1510 enum PrePost
1511 {
1512 	PRE,
1513 	POST
1514 };
1515 
createDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)1516 TestCase* createDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
1517 {
1518 	const BlendState emptyState = BlendState(tcu::Nothing, tcu::Nothing, tcu::Nothing, tcu::Nothing);
1519 
1520 	if (prepost == PRE)
1521 	{
1522 		const BlendState		preState	= BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
1523 														 commonState.blendEq,
1524 														 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
1525 														 tcu::Nothing);
1526 		vector<DrawBufferInfo>	drawBuffers;
1527 
1528 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1529 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1530 
1531 		return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name);
1532 	}
1533 	else if (prepost == POST)
1534 	{
1535 		const BlendState		preState	= BlendState(just(true),
1536 														 tcu::Nothing,
1537 														 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
1538 														 tcu::Nothing);
1539 		vector<DrawBufferInfo>	drawBuffers;
1540 
1541 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1542 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1543 
1544 		return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
1545 	}
1546 	else
1547 	{
1548 		DE_ASSERT(false);
1549 		return DE_NULL;
1550 	}
1551 }
1552 
createAdvancedEqDiffTest(Context & context,PrePost prepost,const char * name,const BlendState & commonState,const BlendState & drawBufferState)1553 TestCase* createAdvancedEqDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState)
1554 {
1555 	const BlendState emptyState = BlendState(tcu::Nothing, tcu::Nothing, tcu::Nothing, tcu::Nothing);
1556 
1557 	if (prepost == PRE)
1558 	{
1559 		const BlendState		preState	= BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)),
1560 														 commonState.blendEq,
1561 														 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))),
1562 														 tcu::Nothing);
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, emptyState, drawBuffers, name, name);
1568 	}
1569 	else if (prepost == POST)
1570 	{
1571 		const BlendState		preState	= BlendState(just(true),
1572 														 tcu::Nothing,
1573 														 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)),
1574 														 tcu::Nothing);
1575 		vector<DrawBufferInfo>	drawBuffers;
1576 
1577 		drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)));
1578 
1579 		return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name);
1580 	}
1581 	else
1582 	{
1583 		DE_ASSERT(false);
1584 		return DE_NULL;
1585 	}
1586 }
1587 
addDrawBufferCommonTests(TestCaseGroup * root,PrePost prepost)1588 void addDrawBufferCommonTests (TestCaseGroup* root, PrePost prepost)
1589 {
1590 	const BlendState		emptyState	= BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1591 
1592 	{
1593 		const BlendState	disableState	= BlendState(just(false), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1594 		const BlendState	enableState		= BlendState(just(true), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1595 
1596 		root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_enable",	enableState,	enableState));
1597 		root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_disable",	disableState,	disableState));
1598 		root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_enable",	disableState,	enableState));
1599 		root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_disable",	enableState,	disableState));
1600 	}
1601 
1602 	{
1603 		const BlendState	eqStateA			= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_ADD), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1604 		const BlendState	eqStateB			= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_SUBTRACT), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1605 
1606 		const BlendState	separateEqStateA	= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_ADD, GL_FUNC_SUBTRACT)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1607 		const BlendState	separateEqStateB	= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_SUBTRACT, GL_FUNC_ADD)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1608 
1609 		const BlendState	advancedEqStateA	= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(GL_DIFFERENCE), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1610 		const BlendState	advancedEqStateB	= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(GL_SCREEN), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1611 
1612 		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_blend_eq", eqStateA, eqStateB));
1613 		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_separate_blend_eq", eqStateA, separateEqStateB));
1614 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_advanced_blend_eq", eqStateA, advancedEqStateB));
1615 
1616 		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_blend_eq", separateEqStateA, eqStateB));
1617 		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_separate_blend_eq", separateEqStateA, separateEqStateB));
1618 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_advanced_blend_eq", separateEqStateA, advancedEqStateB));
1619 
1620 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_blend_eq", advancedEqStateA, eqStateB));
1621 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_separate_blend_eq", advancedEqStateA, separateEqStateB));
1622 		root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_advanced_blend_eq", advancedEqStateA, advancedEqStateB));
1623 	}
1624 
1625 	{
1626 		const BlendState	funcStateA			= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA)), Maybe<BVec4>());
1627 		const BlendState	funcStateB			= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA)), Maybe<BVec4>());
1628 		const BlendState	separateFuncStateA	= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA), BlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA))), Maybe<BVec4>());
1629 		const BlendState	separateFuncStateB	= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA), BlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA))), Maybe<BVec4>());
1630 
1631 		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_blend_func",					funcStateA,			funcStateB));
1632 		root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_separate_blend_func",			funcStateA,			separateFuncStateB));
1633 		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_blend_func",			separateFuncStateA,	funcStateB));
1634 		root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_separate_blend_func",	separateFuncStateA,	separateFuncStateB));
1635 	}
1636 
1637 	{
1638 		const BlendState	commonColorMaskState	= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(true, false, true, false)));
1639 		const BlendState	bufferColorMaskState	= BlendState(tcu::Nothing, Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(false, true, false, true)));
1640 
1641 		root->addChild(createDiffTest(root->getContext(), prepost, "common_color_mask_buffer_color_mask", commonColorMaskState, bufferColorMaskState));
1642 	}
1643 }
1644 
addRandomMaxTest(TestCaseGroup * root)1645 void addRandomMaxTest (TestCaseGroup* root)
1646 {
1647 	for (int i = 0; i < 20; i++)
1648 		root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i));
1649 }
1650 
addRandomImplMaxTest(TestCaseGroup * root)1651 void addRandomImplMaxTest (TestCaseGroup* root)
1652 {
1653 	for (int i = 0; i < 20; i++)
1654 		root->addChild(new ImplMaxDrawBuffersIndexedTest(root->getContext(), i));
1655 }
1656 
1657 } // anonymous
1658 
createDrawBuffersIndexedTests(Context & context)1659 TestCaseGroup* createDrawBuffersIndexedTests (Context& context)
1660 {
1661 	const BlendState		emptyState		= BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>());
1662 	TestCaseGroup* const	group			= new TestCaseGroup(context, "draw_buffers_indexed", "Test for indexed draw buffers. GL_EXT_draw_buffers_indexed.");
1663 
1664 	TestCaseGroup* const	preGroup		= new TestCaseGroup(context, "overwrite_common", "Set common state and overwrite it with draw buffer blend state.");
1665 	TestCaseGroup* const	postGroup		= new TestCaseGroup(context, "overwrite_indexed", "Set indexed blend state and overwrite it with common state.");
1666 	TestCaseGroup* const	randomGroup		= new TestCaseGroup(context, "random", "Random indexed blend state tests.");
1667 	TestCaseGroup* const	maxGroup		= new TestCaseGroup(context, "max_required_draw_buffers", "Random tests using minimum maximum number of draw buffers.");
1668 	TestCaseGroup* const	maxImplGroup	= new TestCaseGroup(context, "max_implementation_draw_buffers", "Random tests using maximum number of draw buffers reported by implementation.");
1669 
1670 	group->addChild(preGroup);
1671 	group->addChild(postGroup);
1672 	group->addChild(randomGroup);
1673 
1674 	randomGroup->addChild(maxGroup);
1675 	randomGroup->addChild(maxImplGroup);
1676 
1677 	addDrawBufferCommonTests(preGroup, PRE);
1678 	addDrawBufferCommonTests(postGroup, POST);
1679 	addRandomMaxTest(maxGroup);
1680 	addRandomImplMaxTest(maxImplGroup);
1681 
1682 	return group;
1683 }
1684 
1685 } // Functional
1686 } // gles3
1687 } // deqp
1688