• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 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 Multisample tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fMultisampleTests.hpp"
25 #include "tcuRenderTarget.hpp"
26 #include "tcuVector.hpp"
27 #include "tcuSurface.hpp"
28 #include "tcuImageCompare.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "gluPixelTransfer.hpp"
31 #include "gluRenderContext.hpp"
32 #include "gluCallLogWrapper.hpp"
33 #include "gluObjectWrapper.hpp"
34 #include "gluShaderProgram.hpp"
35 #include "glwFunctions.hpp"
36 #include "glwEnums.hpp"
37 #include "deRandom.hpp"
38 #include "deStringUtil.hpp"
39 #include "deString.h"
40 #include "deMath.h"
41 
42 using namespace glw;
43 
44 using tcu::TestLog;
45 using tcu::Vec2;
46 using tcu::Vec3;
47 using tcu::Vec4;
48 
49 namespace deqp
50 {
51 namespace gles31
52 {
53 namespace Functional
54 {
55 namespace
56 {
57 
58 using std::map;
59 using std::string;
60 
sampleMaskToString(const std::vector<deUint32> & bitfield,int numBits)61 static std::string sampleMaskToString (const std::vector<deUint32>& bitfield, int numBits)
62 {
63 	std::string result(numBits, '0');
64 
65 	// move from back to front and set chars to 1
66 	for (int wordNdx = 0; wordNdx < (int)bitfield.size(); ++wordNdx)
67 	{
68 		for (int bit = 0; bit < 32; ++bit)
69 		{
70 			const int targetCharNdx = numBits - (wordNdx*32+bit) - 1;
71 
72 			// beginning of the string reached
73 			if (targetCharNdx < 0)
74 				return result;
75 
76 			if ((bitfield[wordNdx] >> bit) & 0x01)
77 				result[targetCharNdx] = '1';
78 		}
79 	}
80 
81 	return result;
82 }
83 
84 /*--------------------------------------------------------------------*//*!
85  * \brief Returns the number of words needed to represent mask of given length
86  *//*--------------------------------------------------------------------*/
getEffectiveSampleMaskWordCount(int highestBitNdx)87 static int getEffectiveSampleMaskWordCount (int highestBitNdx)
88 {
89 	const int wordSize	= 32;
90 	const int maskLen	= highestBitNdx + 1;
91 
92 	return ((maskLen - 1) / wordSize) + 1; // round_up(mask_len /  wordSize)
93 }
94 
95 /*--------------------------------------------------------------------*//*!
96  * \brief Creates sample mask with all less significant bits than nthBit set
97  *//*--------------------------------------------------------------------*/
genAllSetToNthBitSampleMask(int nthBit)98 static std::vector<deUint32> genAllSetToNthBitSampleMask (int nthBit)
99 {
100 	const int				wordSize	= 32;
101 	const int				numWords	= getEffectiveSampleMaskWordCount(nthBit - 1);
102 	const deUint32			topWordBits	= (deUint32)(nthBit - (numWords - 1) * wordSize);
103 	std::vector<deUint32>	mask		(numWords);
104 
105 	for (int ndx = 0; ndx < numWords - 1; ++ndx)
106 		mask[ndx] = 0xFFFFFFFF;
107 
108 	mask[numWords - 1] = deBitMask32(0, (int)topWordBits);
109 	return mask;
110 }
111 
112 class SamplePosQueryCase : public TestCase
113 {
114 public:
115 					SamplePosQueryCase (Context& context, const char* name, const char* desc);
116 private:
117 	void			init				(void);
118 	IterateResult	iterate				(void);
119 };
120 
SamplePosQueryCase(Context & context,const char * name,const char * desc)121 SamplePosQueryCase::SamplePosQueryCase (Context& context, const char* name, const char* desc)
122 	: TestCase(context, name, desc)
123 {
124 }
125 
init(void)126 void SamplePosQueryCase::init (void)
127 {
128 	if (m_context.getRenderTarget().getNumSamples() == 0)
129 		throw tcu::NotSupportedError("No multisample buffers");
130 }
131 
iterate(void)132 SamplePosQueryCase::IterateResult SamplePosQueryCase::iterate (void)
133 {
134 	glu::CallLogWrapper gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
135 	bool				error	= false;
136 
137 	gl.enableLogging(true);
138 
139 	for (int ndx = 0; ndx < m_context.getRenderTarget().getNumSamples(); ++ndx)
140 	{
141 		tcu::Vec2 samplePos = tcu::Vec2(-1, -1);
142 
143 		gl.glGetMultisamplefv(GL_SAMPLE_POSITION, ndx, samplePos.getPtr());
144 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "getMultisamplefv");
145 
146 		// check value range
147 		if (samplePos.x() < 0.0f || samplePos.x() > 1.0f ||
148 			samplePos.y() < 0.0f || samplePos.y() > 1.0f)
149 		{
150 			m_testCtx.getLog() << tcu::TestLog::Message << "Sample " << ndx << " is not in valid range [0,1], got " << samplePos << tcu::TestLog::EndMessage;
151 			error = true;
152 		}
153 	}
154 
155 	if (!error)
156 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
157 	else
158 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid sample pos");
159 
160 	return STOP;
161 }
162 
163 /*--------------------------------------------------------------------*//*!
164  * \brief Abstract base class handling common stuff for default fbo multisample cases.
165  *//*--------------------------------------------------------------------*/
166 class DefaultFBOMultisampleCase : public TestCase
167 {
168 public:
169 								DefaultFBOMultisampleCase	(Context& context, const char* name, const char* desc, int desiredViewportSize);
170 	virtual						~DefaultFBOMultisampleCase	(void);
171 
172 	virtual void				init						(void);
173 	virtual void				deinit						(void);
174 
175 protected:
176 	void						renderTriangle				(const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const;
177 	void						renderTriangle				(const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& color) const;
178 	void						renderTriangle				(const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const;
179 	void						renderTriangle				(const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& color) const;
180 	void						renderQuad					(const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& c0, const Vec4& c1, const Vec4& c2, const Vec4& c3) const;
181 	void						renderQuad					(const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& color) const;
182 
183 	void						randomizeViewport			(void);
184 	void						readImage					(tcu::Surface& dst) const;
185 
186 	int							m_numSamples;
187 
188 	int							m_viewportSize;
189 
190 private:
191 								DefaultFBOMultisampleCase	(const DefaultFBOMultisampleCase& other);
192 	DefaultFBOMultisampleCase&	operator=					(const DefaultFBOMultisampleCase& other);
193 
194 	const int					m_desiredViewportSize;
195 
196 	glu::ShaderProgram*			m_program;
197 	int							m_attrPositionLoc;
198 	int							m_attrColorLoc;
199 
200 	int							m_viewportX;
201 	int							m_viewportY;
202 	de::Random					m_rnd;
203 
204 	bool						m_initCalled;
205 };
206 
DefaultFBOMultisampleCase(Context & context,const char * name,const char * desc,int desiredViewportSize)207 DefaultFBOMultisampleCase::DefaultFBOMultisampleCase (Context& context, const char* name, const char* desc, int desiredViewportSize)
208 	: TestCase				(context, name, desc)
209 	, m_numSamples			(0)
210 	, m_viewportSize		(0)
211 	, m_desiredViewportSize	(desiredViewportSize)
212 	, m_program				(DE_NULL)
213 	, m_attrPositionLoc		(-1)
214 	, m_attrColorLoc		(-1)
215 	, m_viewportX			(0)
216 	, m_viewportY			(0)
217 	, m_rnd					(deStringHash(name))
218 	, m_initCalled			(false)
219 {
220 }
221 
~DefaultFBOMultisampleCase(void)222 DefaultFBOMultisampleCase::~DefaultFBOMultisampleCase (void)
223 {
224 	DefaultFBOMultisampleCase::deinit();
225 }
226 
init(void)227 void DefaultFBOMultisampleCase::init (void)
228 {
229 	const bool					isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
230 	map<string, string>			args;
231 	args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
232 
233 	static const char* vertShaderSource =
234 		"${GLSL_VERSION_DECL}\n"
235 		"in highp vec4 a_position;\n"
236 		"in mediump vec4 a_color;\n"
237 		"out mediump vec4 v_color;\n"
238 		"void main()\n"
239 		"{\n"
240 		"	gl_Position = a_position;\n"
241 		"	v_color = a_color;\n"
242 		"}\n";
243 
244 	static const char* fragShaderSource =
245 		"${GLSL_VERSION_DECL}\n"
246 		"in mediump vec4 v_color;\n"
247 		"layout(location = 0) out mediump vec4 o_color;\n"
248 		"void main()\n"
249 		"{\n"
250 		"	o_color = v_color;\n"
251 		"}\n";
252 
253 	TestLog&				log	= m_testCtx.getLog();
254 	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
255 
256 	if (m_context.getRenderTarget().getNumSamples() <= 1)
257 		throw tcu::NotSupportedError("No multisample buffers");
258 
259 	m_initCalled = true;
260 
261 	// Query and log number of samples per pixel.
262 
263 	gl.getIntegerv(GL_SAMPLES, &m_numSamples);
264 	GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_SAMPLES)");
265 	log << TestLog::Message << "GL_SAMPLES = " << m_numSamples << TestLog::EndMessage;
266 
267 	// Prepare program.
268 
269 	DE_ASSERT(!m_program);
270 
271 	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
272 		<< glu::VertexSource(tcu::StringTemplate(vertShaderSource).specialize(args))
273 		<< glu::FragmentSource(tcu::StringTemplate(fragShaderSource).specialize(args)));
274 	if (!m_program->isOk())
275 		throw tcu::TestError("Failed to compile program", DE_NULL, __FILE__, __LINE__);
276 
277 	m_attrPositionLoc	= gl.getAttribLocation(m_program->getProgram(), "a_position");
278 	m_attrColorLoc		= gl.getAttribLocation(m_program->getProgram(), "a_color");
279 	GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation");
280 
281 	if (m_attrPositionLoc < 0 || m_attrColorLoc < 0)
282 	{
283 		delete m_program;
284 		throw tcu::TestError("Invalid attribute locations", DE_NULL, __FILE__, __LINE__);
285 	}
286 
287 	// Get suitable viewport size.
288 
289 	m_viewportSize = de::min<int>(m_desiredViewportSize, de::min(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight()));
290 	randomizeViewport();
291 }
292 
deinit(void)293 void DefaultFBOMultisampleCase::deinit (void)
294 {
295 	// Do not try to call GL functions during case list creation
296 	if (!m_initCalled)
297 		return;
298 
299 	delete m_program;
300 	m_program = DE_NULL;
301 }
302 
renderTriangle(const Vec3 & p0,const Vec3 & p1,const Vec3 & p2,const Vec4 & c0,const Vec4 & c1,const Vec4 & c2) const303 void DefaultFBOMultisampleCase::renderTriangle (const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const
304 {
305 	const float vertexPositions[] =
306 	{
307 		p0.x(), p0.y(), p0.z(), 1.0f,
308 		p1.x(), p1.y(), p1.z(), 1.0f,
309 		p2.x(), p2.y(), p2.z(), 1.0f
310 	};
311 	const float vertexColors[] =
312 	{
313 		c0.x(), c0.y(), c0.z(), c0.w(),
314 		c1.x(), c1.y(), c1.z(), c1.w(),
315 		c2.x(), c2.y(), c2.z(), c2.w(),
316 	};
317 
318 	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
319 	glu::Buffer				vtxBuf	(m_context.getRenderContext());
320 	glu::Buffer				colBuf	(m_context.getRenderContext());
321 	glu::VertexArray		vao		(m_context.getRenderContext());
322 
323 	gl.bindVertexArray(*vao);
324 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindVertexArray");
325 
326 	gl.bindBuffer(GL_ARRAY_BUFFER, *vtxBuf);
327 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), &vertexPositions[0], GL_STATIC_DRAW);
328 	GLU_EXPECT_NO_ERROR(gl.getError(), "vtx buf");
329 
330 	gl.enableVertexAttribArray(m_attrPositionLoc);
331 	gl.vertexAttribPointer(m_attrPositionLoc, 4, GL_FLOAT, false, 0, DE_NULL);
332 	GLU_EXPECT_NO_ERROR(gl.getError(), "vtx vertexAttribPointer");
333 
334 	gl.bindBuffer(GL_ARRAY_BUFFER, *colBuf);
335 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexColors), &vertexColors[0], GL_STATIC_DRAW);
336 	GLU_EXPECT_NO_ERROR(gl.getError(), "col buf");
337 
338 	gl.enableVertexAttribArray(m_attrColorLoc);
339 	gl.vertexAttribPointer(m_attrColorLoc, 4, GL_FLOAT, false, 0, DE_NULL);
340 	GLU_EXPECT_NO_ERROR(gl.getError(), "col vertexAttribPointer");
341 
342 	gl.useProgram(m_program->getProgram());
343 	gl.drawArrays(GL_TRIANGLES, 0, 3);
344 	GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
345 }
346 
renderTriangle(const Vec3 & p0,const Vec3 & p1,const Vec3 & p2,const Vec4 & color) const347 void DefaultFBOMultisampleCase::renderTriangle (const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& color) const
348 {
349 	renderTriangle(p0, p1, p2, color, color, color);
350 }
351 
renderTriangle(const Vec2 & p0,const Vec2 & p1,const Vec2 & p2,const Vec4 & c0,const Vec4 & c1,const Vec4 & c2) const352 void DefaultFBOMultisampleCase::renderTriangle (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const
353 {
354 	renderTriangle(Vec3(p0.x(), p0.y(), 0.0f),
355 				   Vec3(p1.x(), p1.y(), 0.0f),
356 				   Vec3(p2.x(), p2.y(), 0.0f),
357 				   c0, c1, c2);
358 }
359 
renderTriangle(const Vec2 & p0,const Vec2 & p1,const Vec2 & p2,const Vec4 & color) const360 void DefaultFBOMultisampleCase::renderTriangle (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& color) const
361 {
362 	renderTriangle(p0, p1, p2, color, color, color);
363 }
364 
renderQuad(const Vec2 & p0,const Vec2 & p1,const Vec2 & p2,const Vec2 & p3,const Vec4 & c0,const Vec4 & c1,const Vec4 & c2,const Vec4 & c3) const365 void DefaultFBOMultisampleCase::renderQuad (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& c0, const Vec4& c1, const Vec4& c2, const Vec4& c3) const
366 {
367 	renderTriangle(p0, p1, p2, c0, c1, c2);
368 	renderTriangle(p2, p1, p3, c2, c1, c3);
369 }
370 
renderQuad(const Vec2 & p0,const Vec2 & p1,const Vec2 & p2,const Vec2 & p3,const Vec4 & color) const371 void DefaultFBOMultisampleCase::renderQuad (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& color) const
372 {
373 	renderQuad(p0, p1, p2, p3, color, color, color, color);
374 }
375 
randomizeViewport(void)376 void DefaultFBOMultisampleCase::randomizeViewport (void)
377 {
378 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
379 
380 	m_viewportX = m_rnd.getInt(0, m_context.getRenderTarget().getWidth()  - m_viewportSize);
381 	m_viewportY = m_rnd.getInt(0, m_context.getRenderTarget().getHeight() - m_viewportSize);
382 
383 	gl.viewport(m_viewportX, m_viewportY, m_viewportSize, m_viewportSize);
384 	GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
385 }
386 
readImage(tcu::Surface & dst) const387 void DefaultFBOMultisampleCase::readImage (tcu::Surface& dst) const
388 {
389 	glu::readPixels(m_context.getRenderContext(), m_viewportX, m_viewportY, dst.getAccess());
390 }
391 
392 /*--------------------------------------------------------------------*//*!
393  * \brief Tests coverage mask inversion validity.
394  *
395  * Tests that the coverage masks obtained by masks set with glSampleMaski(mask)
396  * and glSampleMaski(~mask) are indeed each others' inverses.
397  *
398  * This is done by drawing a pattern, with varying coverage values,
399  * overlapped by a pattern that has inverted masks and is otherwise
400  * identical. The resulting image is compared to one obtained by drawing
401  * the same pattern but with all-ones coverage masks.
402  *//*--------------------------------------------------------------------*/
403 class MaskInvertCase : public DefaultFBOMultisampleCase
404 {
405 public:
406 					MaskInvertCase				(Context& context, const char* name, const char* description);
~MaskInvertCase(void)407 					~MaskInvertCase				(void) {}
408 
409 	void			init						(void);
410 	IterateResult	iterate						(void);
411 
412 private:
413 	void			drawPattern					(bool invert) const;
414 };
415 
MaskInvertCase(Context & context,const char * name,const char * description)416 MaskInvertCase::MaskInvertCase (Context& context, const char* name, const char* description)
417 	: DefaultFBOMultisampleCase	(context, name, description, 256)
418 {
419 }
420 
init(void)421 void MaskInvertCase::init (void)
422 {
423 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
424 
425 	// check the test is even possible
426 
427 	GLint maxSampleMaskWords = 0;
428 	gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
429 	if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
430 		throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");
431 
432 	// normal init
433 	DefaultFBOMultisampleCase::init();
434 }
435 
iterate(void)436 MaskInvertCase::IterateResult MaskInvertCase::iterate (void)
437 {
438 	const glw::Functions&	gl = m_context.getRenderContext().getFunctions();
439 	TestLog&				log								= m_testCtx.getLog();
440 	tcu::Surface			renderedImgNoSampleCoverage		(m_viewportSize, m_viewportSize);
441 	tcu::Surface			renderedImgSampleCoverage		(m_viewportSize, m_viewportSize);
442 
443 	randomizeViewport();
444 
445 	gl.enable(GL_BLEND);
446 	gl.blendEquation(GL_FUNC_ADD);
447 	gl.blendFunc(GL_ONE, GL_ONE);
448 	GLU_EXPECT_NO_ERROR(gl.getError(), "set blend");
449 	log << TestLog::Message << "Additive blending enabled in order to detect (erroneously) overlapping samples" << TestLog::EndMessage;
450 
451 	log << TestLog::Message << "Clearing color to all-zeros" << TestLog::EndMessage;
452 	gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
453 	gl.clear(GL_COLOR_BUFFER_BIT);
454 	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
455 
456 	log << TestLog::Message << "Drawing the pattern with GL_SAMPLE_MASK disabled" << TestLog::EndMessage;
457 	drawPattern(false);
458 	readImage(renderedImgNoSampleCoverage);
459 
460 	log << TestLog::Image("RenderedImageNoSampleMask", "Rendered image with GL_SAMPLE_MASK disabled", renderedImgNoSampleCoverage, QP_IMAGE_COMPRESSION_MODE_PNG);
461 
462 	log << TestLog::Message << "Clearing color to all-zeros" << TestLog::EndMessage;
463 	gl.clear(GL_COLOR_BUFFER_BIT);
464 	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
465 
466 	gl.enable(GL_SAMPLE_MASK);
467 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK)");
468 
469 	log << TestLog::Message << "Drawing the pattern with GL_SAMPLE_MASK enabled, using non-inverted sample masks" << TestLog::EndMessage;
470 	drawPattern(false);
471 	log << TestLog::Message << "Drawing the pattern with GL_SAMPLE_MASK enabled, using inverted sample masks" << TestLog::EndMessage;
472 	drawPattern(true);
473 
474 	readImage(renderedImgSampleCoverage);
475 
476 	log << TestLog::Image("RenderedImageSampleMask", "Rendered image with GL_SAMPLE_MASK enabled", renderedImgSampleCoverage, QP_IMAGE_COMPRESSION_MODE_PNG);
477 
478 	bool passed = tcu::pixelThresholdCompare(log,
479 											 "CoverageVsNoCoverage",
480 											 "Comparison of same pattern with GL_SAMPLE_MASK disabled and enabled",
481 											 renderedImgNoSampleCoverage,
482 											 renderedImgSampleCoverage,
483 											 tcu::RGBA(0),
484 											 tcu::COMPARE_LOG_ON_ERROR);
485 
486 	if (passed)
487 		log << TestLog::Message << "Success: The two images rendered are identical" << TestLog::EndMessage;
488 
489 	m_context.getTestContext().setTestResult(passed ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
490 											 passed ? "Passed"				: "Failed");
491 
492 	return STOP;
493 }
494 
drawPattern(bool invert) const495 void MaskInvertCase::drawPattern (bool invert) const
496 {
497 	const int				numTriangles	= 25;
498 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
499 
500 	for (int triNdx = 0; triNdx < numTriangles; triNdx++)
501 	{
502 		const float	angle0	= 2.0f*DE_PI * (float)triNdx			/ (float)numTriangles;
503 		const float	angle1	= 2.0f*DE_PI * ((float)triNdx + 0.5f)	/ (float)numTriangles;
504 		const Vec4	color	= Vec4(0.4f + (float)triNdx/(float)numTriangles*0.6f,
505 		                           0.5f + (float)triNdx/(float)numTriangles*0.3f,
506 		                           0.6f - (float)triNdx/(float)numTriangles*0.5f,
507 		                           0.7f - (float)triNdx/(float)numTriangles*0.7f);
508 
509 
510 		const int			wordCount		= getEffectiveSampleMaskWordCount(m_numSamples - 1);
511 		const GLbitfield	finalWordBits	= m_numSamples - 32 * ((m_numSamples-1) / 32);
512 		const GLbitfield	finalWordMask	= (GLbitfield)deBitMask32(0, (int)finalWordBits);
513 
514 		for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
515 		{
516 			const GLbitfield	rawMask		= (GLbitfield)deUint32Hash(wordNdx * 32 + triNdx);
517 			const GLbitfield	mask		= (invert) ? (~rawMask) : (rawMask);
518 			const bool			isFinalWord	= (wordNdx + 1) == wordCount;
519 			const GLbitfield	maskMask	= (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask prevents setting coverage bits higher than sample count
520 
521 			gl.sampleMaski(wordNdx, mask & maskMask);
522 		}
523 		GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
524 
525 		renderTriangle(Vec2(0.0f, 0.0f),
526 					   Vec2(deFloatCos(angle0)*0.95f, deFloatSin(angle0)*0.95f),
527 					   Vec2(deFloatCos(angle1)*0.95f, deFloatSin(angle1)*0.95f),
528 					   color);
529 	}
530 }
531 
532 /*--------------------------------------------------------------------*//*!
533  * \brief Tests coverage mask generation proportionality property.
534  *
535  * Tests that the number of coverage bits in a coverage mask set with
536  * glSampleMaski is, on average, proportional to the number of set bits.
537  * Draws multiple frames, each time increasing the number of mask bits set
538  * and checks that the average color is changing appropriately.
539  *//*--------------------------------------------------------------------*/
540 class MaskProportionalityCase : public DefaultFBOMultisampleCase
541 {
542 public:
543 					MaskProportionalityCase				(Context& context, const char* name, const char* description);
~MaskProportionalityCase(void)544 					~MaskProportionalityCase			(void) {}
545 
546 	void			init								(void);
547 
548 	IterateResult	iterate								(void);
549 
550 private:
551 	int				m_numIterations;
552 	int				m_currentIteration;
553 
554 	deInt32			m_previousIterationColorSum;
555 };
556 
MaskProportionalityCase(Context & context,const char * name,const char * description)557 MaskProportionalityCase::MaskProportionalityCase (Context& context, const char* name, const char* description)
558 	: DefaultFBOMultisampleCase		(context, name, description, 32)
559 	, m_numIterations				(-1)
560 	, m_currentIteration			(0)
561 	, m_previousIterationColorSum	(-1)
562 {
563 }
564 
init(void)565 void MaskProportionalityCase::init (void)
566 {
567 	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
568 	TestLog&				log	= m_testCtx.getLog();
569 
570 	// check the test is even possible
571 	GLint maxSampleMaskWords = 0;
572 	gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
573 	if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
574 		throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");
575 
576 	DefaultFBOMultisampleCase::init();
577 
578 	// set state
579 	gl.enable(GL_SAMPLE_MASK);
580 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK)");
581 	log << TestLog::Message << "GL_SAMPLE_MASK is enabled" << TestLog::EndMessage;
582 
583 	m_numIterations = m_numSamples + 1;
584 
585 	randomizeViewport(); // \note Using the same viewport for every iteration since coverage mask may depend on window-relative pixel coordinate.
586 }
587 
iterate(void)588 MaskProportionalityCase::IterateResult MaskProportionalityCase::iterate (void)
589 {
590 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
591 	TestLog&				log				= m_testCtx.getLog();
592 	tcu::Surface			renderedImg		(m_viewportSize, m_viewportSize);
593 	deInt32					numPixels		= (deInt32)renderedImg.getWidth()*(deInt32)renderedImg.getHeight();
594 
595 	DE_ASSERT(m_numIterations >= 0);
596 
597 	log << TestLog::Message << "Clearing color to black" << TestLog::EndMessage;
598 	gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
599 	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
600 	gl.clear(GL_COLOR_BUFFER_BIT);
601 	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
602 
603 	// Draw quad.
604 
605 	{
606 		const Vec2					pt0						(-1.0f, -1.0f);
607 		const Vec2					pt1						( 1.0f, -1.0f);
608 		const Vec2					pt2						(-1.0f,  1.0f);
609 		const Vec2					pt3						( 1.0f,  1.0f);
610 		Vec4						quadColor				(1.0f, 0.0f, 0.0f, 1.0f);
611 		const std::vector<deUint32>	sampleMask				= genAllSetToNthBitSampleMask(m_currentIteration);
612 
613 		DE_ASSERT(m_currentIteration <= m_numSamples + 1);
614 
615 		log << TestLog::Message << "Drawing a red quad using sample mask 0b" << sampleMaskToString(sampleMask, m_numSamples) << TestLog::EndMessage;
616 
617 		for (int wordNdx = 0; wordNdx < getEffectiveSampleMaskWordCount(m_numSamples - 1); ++wordNdx)
618 		{
619 			const GLbitfield mask = (wordNdx < (int)sampleMask.size()) ? ((GLbitfield)(sampleMask[wordNdx])) : (0);
620 
621 			gl.sampleMaski(wordNdx, mask);
622 			GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
623 		}
624 
625 		renderQuad(pt0, pt1, pt2, pt3, quadColor);
626 	}
627 
628 	// Read ang log image.
629 
630 	readImage(renderedImg);
631 
632 	log << TestLog::Image("RenderedImage", "Rendered image", renderedImg, QP_IMAGE_COMPRESSION_MODE_PNG);
633 
634 	// Compute average red component in rendered image.
635 
636 	deInt32 sumRed = 0;
637 
638 	for (int y = 0; y < renderedImg.getHeight(); y++)
639 	for (int x = 0; x < renderedImg.getWidth(); x++)
640 		sumRed += renderedImg.getPixel(x, y).getRed();
641 
642 	log << TestLog::Message << "Average red color component: " << de::floatToString((float)sumRed / 255.0f / (float)numPixels, 2) << TestLog::EndMessage;
643 
644 	// Check if average color has decreased from previous frame's color.
645 
646 	if (sumRed < m_previousIterationColorSum)
647 	{
648 		log << TestLog::Message << "Failure: Current average red color component is lower than previous" << TestLog::EndMessage;
649 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
650 		return STOP;
651 	}
652 
653 	// Check if coverage mask is not all-zeros if alpha or coverage value is 0 (or 1, if inverted).
654 
655 	if (m_currentIteration == 0 && sumRed != 0)
656 	{
657 		log << TestLog::Message << "Failure: Image should be completely black" << TestLog::EndMessage;
658 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
659 		return STOP;
660 	}
661 
662 	if (m_currentIteration == m_numIterations-1 && sumRed != 0xff*numPixels)
663 	{
664 		log << TestLog::Message << "Failure: Image should be completely red" << TestLog::EndMessage;
665 
666 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
667 		return STOP;
668 	}
669 
670 	m_previousIterationColorSum = sumRed;
671 
672 	m_currentIteration++;
673 
674 	if (m_currentIteration >= m_numIterations)
675 	{
676 		log << TestLog::Message << "Success: Number of coverage mask bits set appears to be, on average, proportional to the number of set sample mask bits" << TestLog::EndMessage;
677 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
678 		return STOP;
679 	}
680 	else
681 		return CONTINUE;
682 }
683 
684 /*--------------------------------------------------------------------*//*!
685  * \brief Tests coverage mask generation constancy property.
686  *
687  * Tests that the coverage mask created by GL_SAMPLE_MASK is constant at
688  * given pixel coordinates. Draws two quads, with the second one fully
689  * overlapping the first one such that at any given pixel, both quads have
690  * the same coverage mask value. This way, if the constancy property is
691  * fulfilled, only the second quad should be visible.
692  *//*--------------------------------------------------------------------*/
693 class MaskConstancyCase : public DefaultFBOMultisampleCase
694 {
695 public:
696 	enum CaseBits
697 	{
698 		CASEBIT_ALPHA_TO_COVERAGE			= 1,	//!< Use alpha-to-coverage.
699 		CASEBIT_SAMPLE_COVERAGE				= 2,	//!< Use sample coverage.
700 		CASEBIT_SAMPLE_COVERAGE_INVERTED	= 4,	//!< Inverted sample coverage.
701 		CASEBIT_SAMPLE_MASK					= 8,	//!< Use sample mask.
702 	};
703 
704 					MaskConstancyCase			(Context& context, const char* name, const char* description, deUint32 typeBits);
~MaskConstancyCase(void)705 					~MaskConstancyCase			(void) {}
706 
707 	void			init						(void);
708 	IterateResult	iterate						(void);
709 
710 private:
711 	const bool		m_isAlphaToCoverageCase;
712 	const bool		m_isSampleCoverageCase;
713 	const bool		m_isInvertedSampleCoverageCase;
714 	const bool		m_isSampleMaskCase;
715 };
716 
MaskConstancyCase(Context & context,const char * name,const char * description,deUint32 typeBits)717 MaskConstancyCase::MaskConstancyCase (Context& context, const char* name, const char* description, deUint32 typeBits)
718 	: DefaultFBOMultisampleCase			(context, name, description, 256)
719 	, m_isAlphaToCoverageCase			(0 != (typeBits & CASEBIT_ALPHA_TO_COVERAGE))
720 	, m_isSampleCoverageCase			(0 != (typeBits & CASEBIT_SAMPLE_COVERAGE))
721 	, m_isInvertedSampleCoverageCase	(0 != (typeBits & CASEBIT_SAMPLE_COVERAGE_INVERTED))
722 	, m_isSampleMaskCase				(0 != (typeBits & CASEBIT_SAMPLE_MASK))
723 {
724 	// CASEBIT_SAMPLE_COVERAGE_INVERT => CASEBIT_SAMPLE_COVERAGE
725 	DE_ASSERT((typeBits & CASEBIT_SAMPLE_COVERAGE) || ~(typeBits & CASEBIT_SAMPLE_COVERAGE_INVERTED));
726 	DE_ASSERT(m_isSampleMaskCase); // no point testing non-sample-mask cases, they are checked already in gles3
727 }
728 
init(void)729 void MaskConstancyCase::init (void)
730 {
731 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
732 
733 	// check the test is even possible
734 	if (m_isSampleMaskCase)
735 	{
736 		GLint maxSampleMaskWords = 0;
737 		gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
738 		if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
739 			throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");
740 	}
741 
742 	// normal init
743 	DefaultFBOMultisampleCase::init();
744 }
745 
iterate(void)746 MaskConstancyCase::IterateResult MaskConstancyCase::iterate (void)
747 {
748 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
749 	TestLog&				log				= m_testCtx.getLog();
750 	tcu::Surface			renderedImg		(m_viewportSize, m_viewportSize);
751 
752 	randomizeViewport();
753 
754 	log << TestLog::Message << "Clearing color to black" << TestLog::EndMessage;
755 	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
756 	gl.clear(GL_COLOR_BUFFER_BIT);
757 	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
758 
759 	if (m_isAlphaToCoverageCase)
760 	{
761 		gl.enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
762 		gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
763 		GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_ALPHA_TO_COVERAGE");
764 
765 		log << TestLog::Message << "GL_SAMPLE_ALPHA_TO_COVERAGE is enabled" << TestLog::EndMessage;
766 		log << TestLog::Message << "Color mask is TRUE, TRUE, TRUE, FALSE" << TestLog::EndMessage;
767 	}
768 
769 	if (m_isSampleCoverageCase)
770 	{
771 		gl.enable(GL_SAMPLE_COVERAGE);
772 		GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_COVERAGE");
773 
774 		log << TestLog::Message << "GL_SAMPLE_COVERAGE is enabled" << TestLog::EndMessage;
775 	}
776 
777 	if (m_isSampleMaskCase)
778 	{
779 		gl.enable(GL_SAMPLE_MASK);
780 		GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_MASK");
781 
782 		log << TestLog::Message << "GL_SAMPLE_MASK is enabled" << TestLog::EndMessage;
783 	}
784 
785 	log << TestLog::Message
786 		<< "Drawing several green quads, each fully overlapped by a red quad with the same "
787 		<< (m_isAlphaToCoverageCase ? "alpha" : "")
788 		<< (m_isAlphaToCoverageCase && (m_isSampleCoverageCase || m_isSampleMaskCase) ? " and " : "")
789 		<< (m_isInvertedSampleCoverageCase ? "inverted " : "")
790 		<< (m_isSampleCoverageCase ? "sample coverage" : "")
791 		<< (m_isSampleCoverageCase && m_isSampleMaskCase ? " and " : "")
792 		<< (m_isSampleMaskCase ? "sample mask" : "")
793 		<< " values"
794 		<< TestLog::EndMessage;
795 
796 	const int numQuadRowsCols = m_numSamples*4;
797 
798 	for (int row = 0; row < numQuadRowsCols; row++)
799 	{
800 		for (int col = 0; col < numQuadRowsCols; col++)
801 		{
802 			float		x0			= (float)(col+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
803 			float		x1			= (float)(col+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
804 			float		y0			= (float)(row+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
805 			float		y1			= (float)(row+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
806 			const Vec4	baseGreen	(0.0f, 1.0f, 0.0f, 0.0f);
807 			const Vec4	baseRed		(1.0f, 0.0f, 0.0f, 0.0f);
808 			Vec4		alpha0		(0.0f, 0.0f, 0.0f, m_isAlphaToCoverageCase ? (float)col / (float)(numQuadRowsCols-1) : 1.0f);
809 			Vec4		alpha1		(0.0f, 0.0f, 0.0f, m_isAlphaToCoverageCase ? (float)row / (float)(numQuadRowsCols-1) : 1.0f);
810 
811 			if (m_isSampleCoverageCase)
812 			{
813 				float value = (float)(row*numQuadRowsCols + col) / (float)(numQuadRowsCols*numQuadRowsCols-1);
814 				gl.sampleCoverage(m_isInvertedSampleCoverageCase ? 1.0f - value : value, m_isInvertedSampleCoverageCase ? GL_TRUE : GL_FALSE);
815 				GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleCoverage");
816 			}
817 
818 			if (m_isSampleMaskCase)
819 			{
820 				const int			wordCount		= getEffectiveSampleMaskWordCount(m_numSamples - 1);
821 				const GLbitfield	finalWordBits	= m_numSamples - 32 * ((m_numSamples-1) / 32);
822 				const GLbitfield	finalWordMask	= (GLbitfield)deBitMask32(0, (int)finalWordBits);
823 
824 				for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
825 				{
826 					const GLbitfield	mask		= (GLbitfield)deUint32Hash((col << (m_numSamples / 2)) ^ row);
827 					const bool			isFinalWord	= (wordNdx + 1) == wordCount;
828 					const GLbitfield	maskMask	= (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask prevents setting coverage bits higher than sample count
829 
830 					gl.sampleMaski(wordNdx, mask & maskMask);
831 					GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
832 				}
833 			}
834 
835 			renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseGreen + alpha0,	baseGreen + alpha1,	baseGreen + alpha0,	baseGreen + alpha1);
836 			renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseRed + alpha0,	baseRed + alpha1,	baseRed + alpha0,	baseRed + alpha1);
837 		}
838 	}
839 
840 	readImage(renderedImg);
841 
842 	log << TestLog::Image("RenderedImage", "Rendered image", renderedImg, QP_IMAGE_COMPRESSION_MODE_PNG);
843 
844 	for (int y = 0; y < renderedImg.getHeight(); y++)
845 	for (int x = 0; x < renderedImg.getWidth(); x++)
846 	{
847 		if (renderedImg.getPixel(x, y).getGreen() > 0)
848 		{
849 			log << TestLog::Message << "Failure: Non-zero green color component detected - should have been completely overwritten by red quad" << TestLog::EndMessage;
850 			m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
851 			return STOP;
852 		}
853 	}
854 
855 	log << TestLog::Message
856 		<< "Success: Coverage mask appears to be constant at a given pixel coordinate with a given "
857 		<< (m_isAlphaToCoverageCase ? "alpha" : "")
858 		<< (m_isAlphaToCoverageCase && m_isSampleCoverageCase ? " and " : "")
859 		<< (m_isSampleCoverageCase ? "coverage value" : "")
860 		<< TestLog::EndMessage;
861 
862 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
863 
864 	return STOP;
865 }
866 
867 /*--------------------------------------------------------------------*//*!
868  * \brief Tests that unused bits of a sample mask have no effect
869  *
870  * Tests that the bits in the sample mask with positions higher than
871  * the number of samples do not have effect. In multisample fragment
872  * operations the sample mask is ANDed with the fragment coverage value.
873  * The coverage value cannot have the corresponding bits set.
874  *
875  * This is done by drawing a quads with varying sample masks and then
876  * redrawing the quads with identical masks but with the mask's high bits
877  * having different values. Only the latter quad pattern should be visible.
878  *//*--------------------------------------------------------------------*/
879 class SampleMaskHighBitsCase : public DefaultFBOMultisampleCase
880 {
881 public:
882 					SampleMaskHighBitsCase		(Context& context, const char* name, const char* description);
~SampleMaskHighBitsCase(void)883 					~SampleMaskHighBitsCase		(void) {}
884 
885 	void			init						(void);
886 	IterateResult	iterate						(void);
887 };
888 
SampleMaskHighBitsCase(Context & context,const char * name,const char * description)889 SampleMaskHighBitsCase::SampleMaskHighBitsCase (Context& context, const char* name, const char* description)
890 	: DefaultFBOMultisampleCase(context, name, description, 256)
891 {
892 }
893 
init(void)894 void SampleMaskHighBitsCase::init (void)
895 {
896 	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
897 	GLint					 maxSampleMaskWords	= 0;
898 
899 	// check the test is even possible
900 	gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
901 	if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
902 		throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");
903 
904 	// normal init
905 	DefaultFBOMultisampleCase::init();
906 }
907 
iterate(void)908 SampleMaskHighBitsCase::IterateResult SampleMaskHighBitsCase::iterate (void)
909 {
910 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
911 	TestLog&				log				= m_testCtx.getLog();
912 	tcu::Surface			renderedImg		(m_viewportSize, m_viewportSize);
913 	de::Random				rnd				(12345);
914 
915 	if (m_numSamples % 32 == 0)
916 	{
917 		log << TestLog::Message << "Sample count is multiple of word size. No unused high bits in sample mask.\nSkipping." << TestLog::EndMessage;
918 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Skipped");
919 		return STOP;
920 	}
921 
922 	randomizeViewport();
923 
924 	log << TestLog::Message << "Clearing color to black" << TestLog::EndMessage;
925 	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
926 	gl.clear(GL_COLOR_BUFFER_BIT);
927 	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
928 
929 	gl.enable(GL_SAMPLE_MASK);
930 	GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_MASK");
931 	log << TestLog::Message << "GL_SAMPLE_MASK is enabled" << TestLog::EndMessage;
932 	log << TestLog::Message << "Drawing several green quads, each fully overlapped by a red quad with the same effective sample mask values" << TestLog::EndMessage;
933 
934 	const int numQuadRowsCols = m_numSamples*4;
935 
936 	for (int row = 0; row < numQuadRowsCols; row++)
937 	{
938 		for (int col = 0; col < numQuadRowsCols; col++)
939 		{
940 			float				x0				= (float)(col+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
941 			float				x1				= (float)(col+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
942 			float				y0				= (float)(row+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
943 			float				y1				= (float)(row+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
944 			const Vec4			baseGreen		(0.0f, 1.0f, 0.0f, 1.0f);
945 			const Vec4			baseRed			(1.0f, 0.0f, 0.0f, 1.0f);
946 
947 			const int			wordCount		= getEffectiveSampleMaskWordCount(m_numSamples - 1);
948 			const GLbitfield	finalWordBits	= m_numSamples - 32 * ((m_numSamples-1) / 32);
949 			const GLbitfield	finalWordMask	= (GLbitfield)deBitMask32(0, (int)finalWordBits);
950 
951 			for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
952 			{
953 				const GLbitfield	mask		= (GLbitfield)deUint32Hash((col << (m_numSamples / 2)) ^ row);
954 				const bool			isFinalWord	= (wordNdx + 1) == wordCount;
955 				const GLbitfield	maskMask	= (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask is 1 on bits in lower positions than sample count
956 				const GLbitfield	highBits	= rnd.getUint32();
957 
958 				gl.sampleMaski(wordNdx, (mask & maskMask) | (highBits & ~maskMask));
959 				GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
960 			}
961 			renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseGreen, baseGreen, baseGreen, baseGreen);
962 
963 			for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
964 			{
965 				const GLbitfield	mask		= (GLbitfield)deUint32Hash((col << (m_numSamples / 2)) ^ row);
966 				const bool			isFinalWord	= (wordNdx + 1) == wordCount;
967 				const GLbitfield	maskMask	= (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask is 1 on bits in lower positions than sample count
968 				const GLbitfield	highBits	= rnd.getUint32();
969 
970 				gl.sampleMaski(wordNdx, (mask & maskMask) | (highBits & ~maskMask));
971 				GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
972 			}
973 			renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseRed, baseRed, baseRed, baseRed);
974 		}
975 	}
976 
977 	readImage(renderedImg);
978 
979 	log << TestLog::Image("RenderedImage", "Rendered image", renderedImg, QP_IMAGE_COMPRESSION_MODE_PNG);
980 
981 	for (int y = 0; y < renderedImg.getHeight(); y++)
982 	for (int x = 0; x < renderedImg.getWidth(); x++)
983 	{
984 		if (renderedImg.getPixel(x, y).getGreen() > 0)
985 		{
986 			log << TestLog::Message << "Failure: Non-zero green color component detected - should have been completely overwritten by red quad. Mask unused bits have effect." << TestLog::EndMessage;
987 			m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Unused mask bits modified mask");
988 			return STOP;
989 		}
990 	}
991 
992 	log << TestLog::Message << "Success: Coverage mask high bits appear to have no effect." << TestLog::EndMessage;
993 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
994 
995 	return STOP;
996 }
997 
998 } // anonymous
999 
MultisampleTests(Context & context)1000 MultisampleTests::MultisampleTests (Context& context)
1001 	: TestCaseGroup(context, "multisample", "Multisample tests")
1002 {
1003 }
1004 
~MultisampleTests(void)1005 MultisampleTests::~MultisampleTests (void)
1006 {
1007 }
1008 
init(void)1009 void MultisampleTests::init (void)
1010 {
1011 	tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "default_framebuffer", "Test with default framebuffer");
1012 
1013 	addChild(group);
1014 
1015 	// .default_framebuffer
1016 	{
1017 		// sample positions
1018 		group->addChild(new SamplePosQueryCase			(m_context, "sample_position", "test SAMPLE_POSITION"));
1019 
1020 		// sample mask
1021 		group->addChild(new MaskInvertCase				(m_context, "sample_mask_sum_of_inverses",	"Test that mask and its negation's sum equal the fully set mask"));
1022 		group->addChild(new MaskProportionalityCase		(m_context, "proportionality_sample_mask",	"Test the proportionality property of GL_SAMPLE_MASK"));
1023 
1024 		group->addChild(new MaskConstancyCase			(m_context, "constancy_sample_mask",
1025 																	"Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_MASK",
1026 																	MaskConstancyCase::CASEBIT_SAMPLE_MASK));
1027 		group->addChild(new MaskConstancyCase			(m_context, "constancy_alpha_to_coverage_sample_mask",
1028 																	"Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_ALPHA_TO_COVERAGE and GL_SAMPLE_MASK",
1029 																	MaskConstancyCase::CASEBIT_ALPHA_TO_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_MASK));
1030 		group->addChild(new MaskConstancyCase			(m_context, "constancy_sample_coverage_sample_mask",
1031 																	"Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_COVERAGE and GL_SAMPLE_MASK",
1032 																	MaskConstancyCase::CASEBIT_SAMPLE_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_MASK));
1033 		group->addChild(new MaskConstancyCase			(m_context, "constancy_alpha_to_coverage_sample_coverage_sample_mask",
1034 																	"Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE and GL_SAMPLE_MASK",
1035 																	MaskConstancyCase::CASEBIT_ALPHA_TO_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_MASK));
1036 		group->addChild(new SampleMaskHighBitsCase		(m_context, "sample_mask_non_effective_bits",
1037 																	"Test that values of unused bits of a sample mask (bit index > sample count) have no effect"));
1038 	}
1039 }
1040 
1041 } // Functional
1042 } // gles31
1043 } // deqp
1044