/*-------------------------------------------------------------------------
 * 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 "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
{

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] = (deUint32)((1ULL << topWordBits) - (deUint32)1);
	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)
{
	static const char* vertShaderSource =
		"#version 310 es\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 =
		"#version 310 es\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::makeVtxFragSources(vertShaderSource, fragShaderSource));
	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)(1ULL << finalWordBits) - 1UL;

		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)(1ULL << finalWordBits) - 1UL;

				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)(1ULL << finalWordBits) - 1UL;

			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
