/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Multisample tests
 *//*--------------------------------------------------------------------*/

#include "es31fMultisampleTests.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuVector.hpp"
#include "tcuSurface.hpp"
#include "tcuImageCompare.hpp"
#include "tcuStringTemplate.hpp"
#include "gluPixelTransfer.hpp"
#include "gluRenderContext.hpp"
#include "gluCallLogWrapper.hpp"
#include "gluObjectWrapper.hpp"
#include "gluShaderProgram.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
#include "deRandom.hpp"
#include "deStringUtil.hpp"
#include "deString.h"
#include "deMath.h"

using namespace glw;

using tcu::TestLog;
using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace
{

using std::map;
using std::string;

static std::string sampleMaskToString (const std::vector<deUint32>& bitfield, int numBits)
{
	std::string result(numBits, '0');

	// move from back to front and set chars to 1
	for (int wordNdx = 0; wordNdx < (int)bitfield.size(); ++wordNdx)
	{
		for (int bit = 0; bit < 32; ++bit)
		{
			const int targetCharNdx = numBits - (wordNdx*32+bit) - 1;

			// beginning of the string reached
			if (targetCharNdx < 0)
				return result;

			if ((bitfield[wordNdx] >> bit) & 0x01)
				result[targetCharNdx] = '1';
		}
	}

	return result;
}

/*--------------------------------------------------------------------*//*!
 * \brief Returns the number of words needed to represent mask of given length
 *//*--------------------------------------------------------------------*/
static int getEffectiveSampleMaskWordCount (int highestBitNdx)
{
	const int wordSize	= 32;
	const int maskLen	= highestBitNdx + 1;

	return ((maskLen - 1) / wordSize) + 1; // round_up(mask_len /  wordSize)
}

/*--------------------------------------------------------------------*//*!
 * \brief Creates sample mask with all less significant bits than nthBit set
 *//*--------------------------------------------------------------------*/
static std::vector<deUint32> genAllSetToNthBitSampleMask (int nthBit)
{
	const int				wordSize	= 32;
	const int				numWords	= getEffectiveSampleMaskWordCount(nthBit - 1);
	const deUint32			topWordBits	= (deUint32)(nthBit - (numWords - 1) * wordSize);
	std::vector<deUint32>	mask		(numWords);

	for (int ndx = 0; ndx < numWords - 1; ++ndx)
		mask[ndx] = 0xFFFFFFFF;

	mask[numWords - 1] = deBitMask32(0, (int)topWordBits);
	return mask;
}

class SamplePosQueryCase : public TestCase
{
public:
					SamplePosQueryCase (Context& context, const char* name, const char* desc);
private:
	void			init				(void);
	IterateResult	iterate				(void);
};

SamplePosQueryCase::SamplePosQueryCase (Context& context, const char* name, const char* desc)
	: TestCase(context, name, desc)
{
}

void SamplePosQueryCase::init (void)
{
	if (m_context.getRenderTarget().getNumSamples() == 0)
		throw tcu::NotSupportedError("No multisample buffers");
}

SamplePosQueryCase::IterateResult SamplePosQueryCase::iterate (void)
{
	glu::CallLogWrapper gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
	bool				error	= false;

	gl.enableLogging(true);

	for (int ndx = 0; ndx < m_context.getRenderTarget().getNumSamples(); ++ndx)
	{
		tcu::Vec2 samplePos = tcu::Vec2(-1, -1);

		gl.glGetMultisamplefv(GL_SAMPLE_POSITION, ndx, samplePos.getPtr());
		GLU_EXPECT_NO_ERROR(gl.glGetError(), "getMultisamplefv");

		// check value range
		if (samplePos.x() < 0.0f || samplePos.x() > 1.0f ||
			samplePos.y() < 0.0f || samplePos.y() > 1.0f)
		{
			m_testCtx.getLog() << tcu::TestLog::Message << "Sample " << ndx << " is not in valid range [0,1], got " << samplePos << tcu::TestLog::EndMessage;
			error = true;
		}
	}

	if (!error)
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	else
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid sample pos");

	return STOP;
}

/*--------------------------------------------------------------------*//*!
 * \brief Abstract base class handling common stuff for default fbo multisample cases.
 *//*--------------------------------------------------------------------*/
class DefaultFBOMultisampleCase : public TestCase
{
public:
								DefaultFBOMultisampleCase	(Context& context, const char* name, const char* desc, int desiredViewportSize);
	virtual						~DefaultFBOMultisampleCase	(void);

	virtual void				init						(void);
	virtual void				deinit						(void);

protected:
	void						renderTriangle				(const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const;
	void						renderTriangle				(const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& color) const;
	void						renderTriangle				(const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const;
	void						renderTriangle				(const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& color) const;
	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;
	void						renderQuad					(const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& color) const;

	void						randomizeViewport			(void);
	void						readImage					(tcu::Surface& dst) const;

	int							m_numSamples;

	int							m_viewportSize;

private:
								DefaultFBOMultisampleCase	(const DefaultFBOMultisampleCase& other);
	DefaultFBOMultisampleCase&	operator=					(const DefaultFBOMultisampleCase& other);

	const int					m_desiredViewportSize;

	glu::ShaderProgram*			m_program;
	int							m_attrPositionLoc;
	int							m_attrColorLoc;

	int							m_viewportX;
	int							m_viewportY;
	de::Random					m_rnd;

	bool						m_initCalled;
};

DefaultFBOMultisampleCase::DefaultFBOMultisampleCase (Context& context, const char* name, const char* desc, int desiredViewportSize)
	: TestCase				(context, name, desc)
	, m_numSamples			(0)
	, m_viewportSize		(0)
	, m_desiredViewportSize	(desiredViewportSize)
	, m_program				(DE_NULL)
	, m_attrPositionLoc		(-1)
	, m_attrColorLoc		(-1)
	, m_viewportX			(0)
	, m_viewportY			(0)
	, m_rnd					(deStringHash(name))
	, m_initCalled			(false)
{
}

DefaultFBOMultisampleCase::~DefaultFBOMultisampleCase (void)
{
	DefaultFBOMultisampleCase::deinit();
}

void DefaultFBOMultisampleCase::init (void)
{
	const bool					isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
	map<string, string>			args;
	args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);

	static const char* vertShaderSource =
		"${GLSL_VERSION_DECL}\n"
		"in highp vec4 a_position;\n"
		"in mediump vec4 a_color;\n"
		"out mediump vec4 v_color;\n"
		"void main()\n"
		"{\n"
		"	gl_Position = a_position;\n"
		"	v_color = a_color;\n"
		"}\n";

	static const char* fragShaderSource =
		"${GLSL_VERSION_DECL}\n"
		"in mediump vec4 v_color;\n"
		"layout(location = 0) out mediump vec4 o_color;\n"
		"void main()\n"
		"{\n"
		"	o_color = v_color;\n"
		"}\n";

	TestLog&				log	= m_testCtx.getLog();
	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();

	if (m_context.getRenderTarget().getNumSamples() <= 1)
		throw tcu::NotSupportedError("No multisample buffers");

	m_initCalled = true;

	// Query and log number of samples per pixel.

	gl.getIntegerv(GL_SAMPLES, &m_numSamples);
	GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_SAMPLES)");
	log << TestLog::Message << "GL_SAMPLES = " << m_numSamples << TestLog::EndMessage;

	// Prepare program.

	DE_ASSERT(!m_program);

	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
		<< glu::VertexSource(tcu::StringTemplate(vertShaderSource).specialize(args))
		<< glu::FragmentSource(tcu::StringTemplate(fragShaderSource).specialize(args)));
	if (!m_program->isOk())
		throw tcu::TestError("Failed to compile program", DE_NULL, __FILE__, __LINE__);

	m_attrPositionLoc	= gl.getAttribLocation(m_program->getProgram(), "a_position");
	m_attrColorLoc		= gl.getAttribLocation(m_program->getProgram(), "a_color");
	GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation");

	if (m_attrPositionLoc < 0 || m_attrColorLoc < 0)
	{
		delete m_program;
		throw tcu::TestError("Invalid attribute locations", DE_NULL, __FILE__, __LINE__);
	}

	// Get suitable viewport size.

	m_viewportSize = de::min<int>(m_desiredViewportSize, de::min(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight()));
	randomizeViewport();
}

void DefaultFBOMultisampleCase::deinit (void)
{
	// Do not try to call GL functions during case list creation
	if (!m_initCalled)
		return;

	delete m_program;
	m_program = DE_NULL;
}

void DefaultFBOMultisampleCase::renderTriangle (const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const
{
	const float vertexPositions[] =
	{
		p0.x(), p0.y(), p0.z(), 1.0f,
		p1.x(), p1.y(), p1.z(), 1.0f,
		p2.x(), p2.y(), p2.z(), 1.0f
	};
	const float vertexColors[] =
	{
		c0.x(), c0.y(), c0.z(), c0.w(),
		c1.x(), c1.y(), c1.z(), c1.w(),
		c2.x(), c2.y(), c2.z(), c2.w(),
	};

	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
	glu::Buffer				vtxBuf	(m_context.getRenderContext());
	glu::Buffer				colBuf	(m_context.getRenderContext());
	glu::VertexArray		vao		(m_context.getRenderContext());

	gl.bindVertexArray(*vao);
	GLU_EXPECT_NO_ERROR(gl.getError(), "bindVertexArray");

	gl.bindBuffer(GL_ARRAY_BUFFER, *vtxBuf);
	gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), &vertexPositions[0], GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "vtx buf");

	gl.enableVertexAttribArray(m_attrPositionLoc);
	gl.vertexAttribPointer(m_attrPositionLoc, 4, GL_FLOAT, false, 0, DE_NULL);
	GLU_EXPECT_NO_ERROR(gl.getError(), "vtx vertexAttribPointer");

	gl.bindBuffer(GL_ARRAY_BUFFER, *colBuf);
	gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexColors), &vertexColors[0], GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "col buf");

	gl.enableVertexAttribArray(m_attrColorLoc);
	gl.vertexAttribPointer(m_attrColorLoc, 4, GL_FLOAT, false, 0, DE_NULL);
	GLU_EXPECT_NO_ERROR(gl.getError(), "col vertexAttribPointer");

	gl.useProgram(m_program->getProgram());
	gl.drawArrays(GL_TRIANGLES, 0, 3);
	GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
}

void DefaultFBOMultisampleCase::renderTriangle (const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec4& color) const
{
	renderTriangle(p0, p1, p2, color, color, color);
}

void DefaultFBOMultisampleCase::renderTriangle (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& c0, const Vec4& c1, const Vec4& c2) const
{
	renderTriangle(Vec3(p0.x(), p0.y(), 0.0f),
				   Vec3(p1.x(), p1.y(), 0.0f),
				   Vec3(p2.x(), p2.y(), 0.0f),
				   c0, c1, c2);
}

void DefaultFBOMultisampleCase::renderTriangle (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec4& color) const
{
	renderTriangle(p0, p1, p2, color, color, color);
}

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
{
	renderTriangle(p0, p1, p2, c0, c1, c2);
	renderTriangle(p2, p1, p3, c2, c1, c3);
}

void DefaultFBOMultisampleCase::renderQuad (const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& p3, const Vec4& color) const
{
	renderQuad(p0, p1, p2, p3, color, color, color, color);
}

void DefaultFBOMultisampleCase::randomizeViewport (void)
{
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	m_viewportX = m_rnd.getInt(0, m_context.getRenderTarget().getWidth()  - m_viewportSize);
	m_viewportY = m_rnd.getInt(0, m_context.getRenderTarget().getHeight() - m_viewportSize);

	gl.viewport(m_viewportX, m_viewportY, m_viewportSize, m_viewportSize);
	GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
}

void DefaultFBOMultisampleCase::readImage (tcu::Surface& dst) const
{
	glu::readPixels(m_context.getRenderContext(), m_viewportX, m_viewportY, dst.getAccess());
}

/*--------------------------------------------------------------------*//*!
 * \brief Tests coverage mask inversion validity.
 *
 * Tests that the coverage masks obtained by masks set with glSampleMaski(mask)
 * and glSampleMaski(~mask) are indeed each others' inverses.
 *
 * This is done by drawing a pattern, with varying coverage values,
 * overlapped by a pattern that has inverted masks and is otherwise
 * identical. The resulting image is compared to one obtained by drawing
 * the same pattern but with all-ones coverage masks.
 *//*--------------------------------------------------------------------*/
class MaskInvertCase : public DefaultFBOMultisampleCase
{
public:
					MaskInvertCase				(Context& context, const char* name, const char* description);
					~MaskInvertCase				(void) {}

	void			init						(void);
	IterateResult	iterate						(void);

private:
	void			drawPattern					(bool invert) const;
};

MaskInvertCase::MaskInvertCase (Context& context, const char* name, const char* description)
	: DefaultFBOMultisampleCase	(context, name, description, 256)
{
}

void MaskInvertCase::init (void)
{
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	// check the test is even possible

	GLint maxSampleMaskWords = 0;
	gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
	if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
		throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");

	// normal init
	DefaultFBOMultisampleCase::init();
}

MaskInvertCase::IterateResult MaskInvertCase::iterate (void)
{
	const glw::Functions&	gl = m_context.getRenderContext().getFunctions();
	TestLog&				log								= m_testCtx.getLog();
	tcu::Surface			renderedImgNoSampleCoverage		(m_viewportSize, m_viewportSize);
	tcu::Surface			renderedImgSampleCoverage		(m_viewportSize, m_viewportSize);

	randomizeViewport();

	gl.enable(GL_BLEND);
	gl.blendEquation(GL_FUNC_ADD);
	gl.blendFunc(GL_ONE, GL_ONE);
	GLU_EXPECT_NO_ERROR(gl.getError(), "set blend");
	log << TestLog::Message << "Additive blending enabled in order to detect (erroneously) overlapping samples" << TestLog::EndMessage;

	log << TestLog::Message << "Clearing color to all-zeros" << TestLog::EndMessage;
	gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
	gl.clear(GL_COLOR_BUFFER_BIT);
	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");

	log << TestLog::Message << "Drawing the pattern with GL_SAMPLE_MASK disabled" << TestLog::EndMessage;
	drawPattern(false);
	readImage(renderedImgNoSampleCoverage);

	log << TestLog::Image("RenderedImageNoSampleMask", "Rendered image with GL_SAMPLE_MASK disabled", renderedImgNoSampleCoverage, QP_IMAGE_COMPRESSION_MODE_PNG);

	log << TestLog::Message << "Clearing color to all-zeros" << TestLog::EndMessage;
	gl.clear(GL_COLOR_BUFFER_BIT);
	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");

	gl.enable(GL_SAMPLE_MASK);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK)");

	log << TestLog::Message << "Drawing the pattern with GL_SAMPLE_MASK enabled, using non-inverted sample masks" << TestLog::EndMessage;
	drawPattern(false);
	log << TestLog::Message << "Drawing the pattern with GL_SAMPLE_MASK enabled, using inverted sample masks" << TestLog::EndMessage;
	drawPattern(true);

	readImage(renderedImgSampleCoverage);

	log << TestLog::Image("RenderedImageSampleMask", "Rendered image with GL_SAMPLE_MASK enabled", renderedImgSampleCoverage, QP_IMAGE_COMPRESSION_MODE_PNG);

	bool passed = tcu::pixelThresholdCompare(log,
											 "CoverageVsNoCoverage",
											 "Comparison of same pattern with GL_SAMPLE_MASK disabled and enabled",
											 renderedImgNoSampleCoverage,
											 renderedImgSampleCoverage,
											 tcu::RGBA(0),
											 tcu::COMPARE_LOG_ON_ERROR);

	if (passed)
		log << TestLog::Message << "Success: The two images rendered are identical" << TestLog::EndMessage;

	m_context.getTestContext().setTestResult(passed ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
											 passed ? "Passed"				: "Failed");

	return STOP;
}

void MaskInvertCase::drawPattern (bool invert) const
{
	const int				numTriangles	= 25;
	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();

	for (int triNdx = 0; triNdx < numTriangles; triNdx++)
	{
		const float	angle0	= 2.0f*DE_PI * (float)triNdx			/ (float)numTriangles;
		const float	angle1	= 2.0f*DE_PI * ((float)triNdx + 0.5f)	/ (float)numTriangles;
		const Vec4	color	= Vec4(0.4f + (float)triNdx/(float)numTriangles*0.6f,
		                           0.5f + (float)triNdx/(float)numTriangles*0.3f,
		                           0.6f - (float)triNdx/(float)numTriangles*0.5f,
		                           0.7f - (float)triNdx/(float)numTriangles*0.7f);


		const int			wordCount		= getEffectiveSampleMaskWordCount(m_numSamples - 1);
		const GLbitfield	finalWordBits	= m_numSamples - 32 * ((m_numSamples-1) / 32);
		const GLbitfield	finalWordMask	= (GLbitfield)deBitMask32(0, (int)finalWordBits);

		for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
		{
			const GLbitfield	rawMask		= (GLbitfield)deUint32Hash(wordNdx * 32 + triNdx);
			const GLbitfield	mask		= (invert) ? (~rawMask) : (rawMask);
			const bool			isFinalWord	= (wordNdx + 1) == wordCount;
			const GLbitfield	maskMask	= (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask prevents setting coverage bits higher than sample count

			gl.sampleMaski(wordNdx, mask & maskMask);
		}
		GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");

		renderTriangle(Vec2(0.0f, 0.0f),
					   Vec2(deFloatCos(angle0)*0.95f, deFloatSin(angle0)*0.95f),
					   Vec2(deFloatCos(angle1)*0.95f, deFloatSin(angle1)*0.95f),
					   color);
	}
}

/*--------------------------------------------------------------------*//*!
 * \brief Tests coverage mask generation proportionality property.
 *
 * Tests that the number of coverage bits in a coverage mask set with
 * glSampleMaski is, on average, proportional to the number of set bits.
 * Draws multiple frames, each time increasing the number of mask bits set
 * and checks that the average color is changing appropriately.
 *//*--------------------------------------------------------------------*/
class MaskProportionalityCase : public DefaultFBOMultisampleCase
{
public:
					MaskProportionalityCase				(Context& context, const char* name, const char* description);
					~MaskProportionalityCase			(void) {}

	void			init								(void);

	IterateResult	iterate								(void);

private:
	int				m_numIterations;
	int				m_currentIteration;

	deInt32			m_previousIterationColorSum;
};

MaskProportionalityCase::MaskProportionalityCase (Context& context, const char* name, const char* description)
	: DefaultFBOMultisampleCase		(context, name, description, 32)
	, m_numIterations				(-1)
	, m_currentIteration			(0)
	, m_previousIterationColorSum	(-1)
{
}

void MaskProportionalityCase::init (void)
{
	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
	TestLog&				log	= m_testCtx.getLog();

	// check the test is even possible
	GLint maxSampleMaskWords = 0;
	gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
	if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
		throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");

	DefaultFBOMultisampleCase::init();

	// set state
	gl.enable(GL_SAMPLE_MASK);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK)");
	log << TestLog::Message << "GL_SAMPLE_MASK is enabled" << TestLog::EndMessage;

	m_numIterations = m_numSamples + 1;

	randomizeViewport(); // \note Using the same viewport for every iteration since coverage mask may depend on window-relative pixel coordinate.
}

MaskProportionalityCase::IterateResult MaskProportionalityCase::iterate (void)
{
	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
	TestLog&				log				= m_testCtx.getLog();
	tcu::Surface			renderedImg		(m_viewportSize, m_viewportSize);
	deInt32					numPixels		= (deInt32)renderedImg.getWidth()*(deInt32)renderedImg.getHeight();

	DE_ASSERT(m_numIterations >= 0);

	log << TestLog::Message << "Clearing color to black" << TestLog::EndMessage;
	gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	gl.clear(GL_COLOR_BUFFER_BIT);
	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");

	// Draw quad.

	{
		const Vec2					pt0						(-1.0f, -1.0f);
		const Vec2					pt1						( 1.0f, -1.0f);
		const Vec2					pt2						(-1.0f,  1.0f);
		const Vec2					pt3						( 1.0f,  1.0f);
		Vec4						quadColor				(1.0f, 0.0f, 0.0f, 1.0f);
		const std::vector<deUint32>	sampleMask				= genAllSetToNthBitSampleMask(m_currentIteration);

		DE_ASSERT(m_currentIteration <= m_numSamples + 1);

		log << TestLog::Message << "Drawing a red quad using sample mask 0b" << sampleMaskToString(sampleMask, m_numSamples) << TestLog::EndMessage;

		for (int wordNdx = 0; wordNdx < getEffectiveSampleMaskWordCount(m_numSamples - 1); ++wordNdx)
		{
			const GLbitfield mask = (wordNdx < (int)sampleMask.size()) ? ((GLbitfield)(sampleMask[wordNdx])) : (0);

			gl.sampleMaski(wordNdx, mask);
			GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
		}

		renderQuad(pt0, pt1, pt2, pt3, quadColor);
	}

	// Read ang log image.

	readImage(renderedImg);

	log << TestLog::Image("RenderedImage", "Rendered image", renderedImg, QP_IMAGE_COMPRESSION_MODE_PNG);

	// Compute average red component in rendered image.

	deInt32 sumRed = 0;

	for (int y = 0; y < renderedImg.getHeight(); y++)
	for (int x = 0; x < renderedImg.getWidth(); x++)
		sumRed += renderedImg.getPixel(x, y).getRed();

	log << TestLog::Message << "Average red color component: " << de::floatToString((float)sumRed / 255.0f / (float)numPixels, 2) << TestLog::EndMessage;

	// Check if average color has decreased from previous frame's color.

	if (sumRed < m_previousIterationColorSum)
	{
		log << TestLog::Message << "Failure: Current average red color component is lower than previous" << TestLog::EndMessage;
		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
		return STOP;
	}

	// Check if coverage mask is not all-zeros if alpha or coverage value is 0 (or 1, if inverted).

	if (m_currentIteration == 0 && sumRed != 0)
	{
		log << TestLog::Message << "Failure: Image should be completely black" << TestLog::EndMessage;
		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
		return STOP;
	}

	if (m_currentIteration == m_numIterations-1 && sumRed != 0xff*numPixels)
	{
		log << TestLog::Message << "Failure: Image should be completely red" << TestLog::EndMessage;

		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
		return STOP;
	}

	m_previousIterationColorSum = sumRed;

	m_currentIteration++;

	if (m_currentIteration >= m_numIterations)
	{
		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;
		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
		return STOP;
	}
	else
		return CONTINUE;
}

/*--------------------------------------------------------------------*//*!
 * \brief Tests coverage mask generation constancy property.
 *
 * Tests that the coverage mask created by GL_SAMPLE_MASK is constant at
 * given pixel coordinates. Draws two quads, with the second one fully
 * overlapping the first one such that at any given pixel, both quads have
 * the same coverage mask value. This way, if the constancy property is
 * fulfilled, only the second quad should be visible.
 *//*--------------------------------------------------------------------*/
class MaskConstancyCase : public DefaultFBOMultisampleCase
{
public:
	enum CaseBits
	{
		CASEBIT_ALPHA_TO_COVERAGE			= 1,	//!< Use alpha-to-coverage.
		CASEBIT_SAMPLE_COVERAGE				= 2,	//!< Use sample coverage.
		CASEBIT_SAMPLE_COVERAGE_INVERTED	= 4,	//!< Inverted sample coverage.
		CASEBIT_SAMPLE_MASK					= 8,	//!< Use sample mask.
	};

					MaskConstancyCase			(Context& context, const char* name, const char* description, deUint32 typeBits);
					~MaskConstancyCase			(void) {}

	void			init						(void);
	IterateResult	iterate						(void);

private:
	const bool		m_isAlphaToCoverageCase;
	const bool		m_isSampleCoverageCase;
	const bool		m_isInvertedSampleCoverageCase;
	const bool		m_isSampleMaskCase;
};

MaskConstancyCase::MaskConstancyCase (Context& context, const char* name, const char* description, deUint32 typeBits)
	: DefaultFBOMultisampleCase			(context, name, description, 256)
	, m_isAlphaToCoverageCase			(0 != (typeBits & CASEBIT_ALPHA_TO_COVERAGE))
	, m_isSampleCoverageCase			(0 != (typeBits & CASEBIT_SAMPLE_COVERAGE))
	, m_isInvertedSampleCoverageCase	(0 != (typeBits & CASEBIT_SAMPLE_COVERAGE_INVERTED))
	, m_isSampleMaskCase				(0 != (typeBits & CASEBIT_SAMPLE_MASK))
{
	// CASEBIT_SAMPLE_COVERAGE_INVERT => CASEBIT_SAMPLE_COVERAGE
	DE_ASSERT((typeBits & CASEBIT_SAMPLE_COVERAGE) || ~(typeBits & CASEBIT_SAMPLE_COVERAGE_INVERTED));
	DE_ASSERT(m_isSampleMaskCase); // no point testing non-sample-mask cases, they are checked already in gles3
}

void MaskConstancyCase::init (void)
{
	const glw::Functions& gl = m_context.getRenderContext().getFunctions();

	// check the test is even possible
	if (m_isSampleMaskCase)
	{
		GLint maxSampleMaskWords = 0;
		gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
		if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
			throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");
	}

	// normal init
	DefaultFBOMultisampleCase::init();
}

MaskConstancyCase::IterateResult MaskConstancyCase::iterate (void)
{
	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
	TestLog&				log				= m_testCtx.getLog();
	tcu::Surface			renderedImg		(m_viewportSize, m_viewportSize);

	randomizeViewport();

	log << TestLog::Message << "Clearing color to black" << TestLog::EndMessage;
	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	gl.clear(GL_COLOR_BUFFER_BIT);
	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");

	if (m_isAlphaToCoverageCase)
	{
		gl.enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
		gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
		GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_ALPHA_TO_COVERAGE");

		log << TestLog::Message << "GL_SAMPLE_ALPHA_TO_COVERAGE is enabled" << TestLog::EndMessage;
		log << TestLog::Message << "Color mask is TRUE, TRUE, TRUE, FALSE" << TestLog::EndMessage;
	}

	if (m_isSampleCoverageCase)
	{
		gl.enable(GL_SAMPLE_COVERAGE);
		GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_COVERAGE");

		log << TestLog::Message << "GL_SAMPLE_COVERAGE is enabled" << TestLog::EndMessage;
	}

	if (m_isSampleMaskCase)
	{
		gl.enable(GL_SAMPLE_MASK);
		GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_MASK");

		log << TestLog::Message << "GL_SAMPLE_MASK is enabled" << TestLog::EndMessage;
	}

	log << TestLog::Message
		<< "Drawing several green quads, each fully overlapped by a red quad with the same "
		<< (m_isAlphaToCoverageCase ? "alpha" : "")
		<< (m_isAlphaToCoverageCase && (m_isSampleCoverageCase || m_isSampleMaskCase) ? " and " : "")
		<< (m_isInvertedSampleCoverageCase ? "inverted " : "")
		<< (m_isSampleCoverageCase ? "sample coverage" : "")
		<< (m_isSampleCoverageCase && m_isSampleMaskCase ? " and " : "")
		<< (m_isSampleMaskCase ? "sample mask" : "")
		<< " values"
		<< TestLog::EndMessage;

	const int numQuadRowsCols = m_numSamples*4;

	for (int row = 0; row < numQuadRowsCols; row++)
	{
		for (int col = 0; col < numQuadRowsCols; col++)
		{
			float		x0			= (float)(col+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
			float		x1			= (float)(col+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
			float		y0			= (float)(row+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
			float		y1			= (float)(row+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
			const Vec4	baseGreen	(0.0f, 1.0f, 0.0f, 0.0f);
			const Vec4	baseRed		(1.0f, 0.0f, 0.0f, 0.0f);
			Vec4		alpha0		(0.0f, 0.0f, 0.0f, m_isAlphaToCoverageCase ? (float)col / (float)(numQuadRowsCols-1) : 1.0f);
			Vec4		alpha1		(0.0f, 0.0f, 0.0f, m_isAlphaToCoverageCase ? (float)row / (float)(numQuadRowsCols-1) : 1.0f);

			if (m_isSampleCoverageCase)
			{
				float value = (float)(row*numQuadRowsCols + col) / (float)(numQuadRowsCols*numQuadRowsCols-1);
				gl.sampleCoverage(m_isInvertedSampleCoverageCase ? 1.0f - value : value, m_isInvertedSampleCoverageCase ? GL_TRUE : GL_FALSE);
				GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleCoverage");
			}

			if (m_isSampleMaskCase)
			{
				const int			wordCount		= getEffectiveSampleMaskWordCount(m_numSamples - 1);
				const GLbitfield	finalWordBits	= m_numSamples - 32 * ((m_numSamples-1) / 32);
				const GLbitfield	finalWordMask	= (GLbitfield)deBitMask32(0, (int)finalWordBits);

				for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
				{
					const GLbitfield	mask		= (GLbitfield)deUint32Hash((col << (m_numSamples / 2)) ^ row);
					const bool			isFinalWord	= (wordNdx + 1) == wordCount;
					const GLbitfield	maskMask	= (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask prevents setting coverage bits higher than sample count

					gl.sampleMaski(wordNdx, mask & maskMask);
					GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
				}
			}

			renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseGreen + alpha0,	baseGreen + alpha1,	baseGreen + alpha0,	baseGreen + alpha1);
			renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseRed + alpha0,	baseRed + alpha1,	baseRed + alpha0,	baseRed + alpha1);
		}
	}

	readImage(renderedImg);

	log << TestLog::Image("RenderedImage", "Rendered image", renderedImg, QP_IMAGE_COMPRESSION_MODE_PNG);

	for (int y = 0; y < renderedImg.getHeight(); y++)
	for (int x = 0; x < renderedImg.getWidth(); x++)
	{
		if (renderedImg.getPixel(x, y).getGreen() > 0)
		{
			log << TestLog::Message << "Failure: Non-zero green color component detected - should have been completely overwritten by red quad" << TestLog::EndMessage;
			m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Failed");
			return STOP;
		}
	}

	log << TestLog::Message
		<< "Success: Coverage mask appears to be constant at a given pixel coordinate with a given "
		<< (m_isAlphaToCoverageCase ? "alpha" : "")
		<< (m_isAlphaToCoverageCase && m_isSampleCoverageCase ? " and " : "")
		<< (m_isSampleCoverageCase ? "coverage value" : "")
		<< TestLog::EndMessage;

	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");

	return STOP;
}

/*--------------------------------------------------------------------*//*!
 * \brief Tests that unused bits of a sample mask have no effect
 *
 * Tests that the bits in the sample mask with positions higher than
 * the number of samples do not have effect. In multisample fragment
 * operations the sample mask is ANDed with the fragment coverage value.
 * The coverage value cannot have the corresponding bits set.
 *
 * This is done by drawing a quads with varying sample masks and then
 * redrawing the quads with identical masks but with the mask's high bits
 * having different values. Only the latter quad pattern should be visible.
 *//*--------------------------------------------------------------------*/
class SampleMaskHighBitsCase : public DefaultFBOMultisampleCase
{
public:
					SampleMaskHighBitsCase		(Context& context, const char* name, const char* description);
					~SampleMaskHighBitsCase		(void) {}

	void			init						(void);
	IterateResult	iterate						(void);
};

SampleMaskHighBitsCase::SampleMaskHighBitsCase (Context& context, const char* name, const char* description)
	: DefaultFBOMultisampleCase(context, name, description, 256)
{
}

void SampleMaskHighBitsCase::init (void)
{
	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
	GLint					 maxSampleMaskWords	= 0;

	// check the test is even possible
	gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &maxSampleMaskWords);
	if (getEffectiveSampleMaskWordCount(m_numSamples - 1) > maxSampleMaskWords)
		throw tcu::NotSupportedError("Test requires larger GL_MAX_SAMPLE_MASK_WORDS");

	// normal init
	DefaultFBOMultisampleCase::init();
}

SampleMaskHighBitsCase::IterateResult SampleMaskHighBitsCase::iterate (void)
{
	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
	TestLog&				log				= m_testCtx.getLog();
	tcu::Surface			renderedImg		(m_viewportSize, m_viewportSize);
	de::Random				rnd				(12345);

	if (m_numSamples % 32 == 0)
	{
		log << TestLog::Message << "Sample count is multiple of word size. No unused high bits in sample mask.\nSkipping." << TestLog::EndMessage;
		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Skipped");
		return STOP;
	}

	randomizeViewport();

	log << TestLog::Message << "Clearing color to black" << TestLog::EndMessage;
	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	gl.clear(GL_COLOR_BUFFER_BIT);
	GLU_EXPECT_NO_ERROR(gl.getError(), "clear");

	gl.enable(GL_SAMPLE_MASK);
	GLU_EXPECT_NO_ERROR(gl.getError(), "enable GL_SAMPLE_MASK");
	log << TestLog::Message << "GL_SAMPLE_MASK is enabled" << TestLog::EndMessage;
	log << TestLog::Message << "Drawing several green quads, each fully overlapped by a red quad with the same effective sample mask values" << TestLog::EndMessage;

	const int numQuadRowsCols = m_numSamples*4;

	for (int row = 0; row < numQuadRowsCols; row++)
	{
		for (int col = 0; col < numQuadRowsCols; col++)
		{
			float				x0				= (float)(col+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
			float				x1				= (float)(col+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
			float				y0				= (float)(row+0) / (float)numQuadRowsCols * 2.0f - 1.0f;
			float				y1				= (float)(row+1) / (float)numQuadRowsCols * 2.0f - 1.0f;
			const Vec4			baseGreen		(0.0f, 1.0f, 0.0f, 1.0f);
			const Vec4			baseRed			(1.0f, 0.0f, 0.0f, 1.0f);

			const int			wordCount		= getEffectiveSampleMaskWordCount(m_numSamples - 1);
			const GLbitfield	finalWordBits	= m_numSamples - 32 * ((m_numSamples-1) / 32);
			const GLbitfield	finalWordMask	= (GLbitfield)deBitMask32(0, (int)finalWordBits);

			for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
			{
				const GLbitfield	mask		= (GLbitfield)deUint32Hash((col << (m_numSamples / 2)) ^ row);
				const bool			isFinalWord	= (wordNdx + 1) == wordCount;
				const GLbitfield	maskMask	= (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask is 1 on bits in lower positions than sample count
				const GLbitfield	highBits	= rnd.getUint32();

				gl.sampleMaski(wordNdx, (mask & maskMask) | (highBits & ~maskMask));
				GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
			}
			renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseGreen, baseGreen, baseGreen, baseGreen);

			for (int wordNdx = 0; wordNdx < wordCount; ++wordNdx)
			{
				const GLbitfield	mask		= (GLbitfield)deUint32Hash((col << (m_numSamples / 2)) ^ row);
				const bool			isFinalWord	= (wordNdx + 1) == wordCount;
				const GLbitfield	maskMask	= (isFinalWord) ? (finalWordMask) : (0xFFFFFFFFUL); // maskMask is 1 on bits in lower positions than sample count
				const GLbitfield	highBits	= rnd.getUint32();

				gl.sampleMaski(wordNdx, (mask & maskMask) | (highBits & ~maskMask));
				GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski");
			}
			renderQuad(Vec2(x0, y0), Vec2(x1, y0), Vec2(x0, y1), Vec2(x1, y1), baseRed, baseRed, baseRed, baseRed);
		}
	}

	readImage(renderedImg);

	log << TestLog::Image("RenderedImage", "Rendered image", renderedImg, QP_IMAGE_COMPRESSION_MODE_PNG);

	for (int y = 0; y < renderedImg.getHeight(); y++)
	for (int x = 0; x < renderedImg.getWidth(); x++)
	{
		if (renderedImg.getPixel(x, y).getGreen() > 0)
		{
			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;
			m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Unused mask bits modified mask");
			return STOP;
		}
	}

	log << TestLog::Message << "Success: Coverage mask high bits appear to have no effect." << TestLog::EndMessage;
	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");

	return STOP;
}

} // anonymous

MultisampleTests::MultisampleTests (Context& context)
	: TestCaseGroup(context, "multisample", "Multisample tests")
{
}

MultisampleTests::~MultisampleTests (void)
{
}

void MultisampleTests::init (void)
{
	tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "default_framebuffer", "Test with default framebuffer");

	addChild(group);

	// .default_framebuffer
	{
		// sample positions
		group->addChild(new SamplePosQueryCase			(m_context, "sample_position", "test SAMPLE_POSITION"));

		// sample mask
		group->addChild(new MaskInvertCase				(m_context, "sample_mask_sum_of_inverses",	"Test that mask and its negation's sum equal the fully set mask"));
		group->addChild(new MaskProportionalityCase		(m_context, "proportionality_sample_mask",	"Test the proportionality property of GL_SAMPLE_MASK"));

		group->addChild(new MaskConstancyCase			(m_context, "constancy_sample_mask",
																	"Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_MASK",
																	MaskConstancyCase::CASEBIT_SAMPLE_MASK));
		group->addChild(new MaskConstancyCase			(m_context, "constancy_alpha_to_coverage_sample_mask",
																	"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",
																	MaskConstancyCase::CASEBIT_ALPHA_TO_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_MASK));
		group->addChild(new MaskConstancyCase			(m_context, "constancy_sample_coverage_sample_mask",
																	"Test that coverage mask is constant at given coordinates with a given alpha or coverage value, using GL_SAMPLE_COVERAGE and GL_SAMPLE_MASK",
																	MaskConstancyCase::CASEBIT_SAMPLE_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_MASK));
		group->addChild(new MaskConstancyCase			(m_context, "constancy_alpha_to_coverage_sample_coverage_sample_mask",
																	"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",
																	MaskConstancyCase::CASEBIT_ALPHA_TO_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_COVERAGE | MaskConstancyCase::CASEBIT_SAMPLE_MASK));
		group->addChild(new SampleMaskHighBitsCase		(m_context, "sample_mask_non_effective_bits",
																	"Test that values of unused bits of a sample mask (bit index > sample count) have no effect"));
	}
}

} // Functional
} // gles31
} // deqp
