/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 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 Object lifetime tests.
 *//*--------------------------------------------------------------------*/

#include "es3fLifetimeTests.hpp"

#include "deRandom.hpp"
#include "deUniquePtr.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuSurface.hpp"
#include "gluDrawUtil.hpp"
#include "gluObjectWrapper.hpp"
#include "gluPixelTransfer.hpp"
#include "gluShaderProgram.hpp"
#include "glsLifetimeTests.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"

#include <vector>

namespace deqp
{
namespace gles3
{
namespace Functional
{
namespace
{

using std::vector;
using de::MovePtr;
using de::Random;
using tcu::RenderTarget;
using tcu::Surface;
using tcu::TestContext;
using tcu::TestLog;
using glu::CallLogWrapper;
using glu::RenderContext;
using glu::ProgramSources;
using glu::VertexArray;
using glu::Buffer;
namespace lt = gls::LifetimeTests;
using namespace lt;
using namespace glw;
typedef TestCase::IterateResult IterateResult;

enum { VIEWPORT_SIZE = 128 };

class ScaleProgram : public glu::ShaderProgram
{
public:
							ScaleProgram	(lt::Context& ctx);
	void					draw			(GLuint vao, GLfloat scale, bool tf, Surface* dst);
	void					setPos			(GLuint buffer, GLuint vao);

private:
	ProgramSources			getSources		(void);

	const RenderContext&	m_renderCtx;
	GLint					m_scaleLoc;
	GLint					m_posLoc;
};

enum { NUM_COMPONENTS = 4, NUM_VERTICES = 3 };

ScaleProgram::ScaleProgram (lt::Context& ctx)
	: glu::ShaderProgram	(ctx.getRenderContext(), getSources())
	, m_renderCtx			(ctx.getRenderContext())
{
	const Functions& gl = m_renderCtx.getFunctions();
	TCU_CHECK(isOk());
	m_scaleLoc = gl.getUniformLocation(getProgram(), "scale");
	m_posLoc = gl.getAttribLocation(getProgram(), "pos");
}

#define GLSL(VERSION, BODY) ("#version " #VERSION "\n" #BODY "\n")

static const char* const s_vertexShaderSrc = GLSL(
	100,
	attribute vec4 pos;
	uniform float scale;
	void main ()
	{
		gl_Position = vec4(scale * pos.xy, pos.zw);
	}
	);

static const char* const s_fragmentShaderSrc = GLSL(
	100,
	void main ()
	{
		gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
	}
	);

ProgramSources ScaleProgram::getSources (void)
{
	using namespace glu;
	ProgramSources sources;
	sources << VertexSource(s_vertexShaderSrc)
			<< FragmentSource(s_fragmentShaderSrc)
			<< TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS)
			<< TransformFeedbackVarying("gl_Position");
	return sources;
}

void ScaleProgram::draw (GLuint vao, GLfloat scale, bool tf, Surface* dst)
{
	const Functions&	gl			= m_renderCtx.getFunctions();
	de::Random			rnd			(vao);
	Rectangle			viewport	= randomViewport(m_renderCtx,
													 VIEWPORT_SIZE, VIEWPORT_SIZE, rnd);
	setViewport(m_renderCtx, viewport);
	gl.clearColor(0, 0, 0, 1);
	gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	gl.bindVertexArray(vao);
	gl.enableVertexAttribArray(m_posLoc);
	GLU_CHECK_CALL_ERROR(gl.useProgram(getProgram()),
						 gl.getError());

	gl.uniform1f(m_scaleLoc, scale);

	if (tf)
		gl.beginTransformFeedback(GL_TRIANGLES);
	GLU_CHECK_CALL_ERROR(gl.drawArrays(GL_TRIANGLES, 0, 3), gl.getError());
	if (tf)
		gl.endTransformFeedback();

	if (dst != DE_NULL)
		readRectangle(m_renderCtx, viewport, *dst);

	gl.bindVertexArray(0);
}

void ScaleProgram::setPos (GLuint buffer, GLuint vao)
{
	const Functions& gl = m_renderCtx.getFunctions();

	gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
	gl.bindVertexArray(vao);
	GLU_CHECK_CALL_ERROR(
		gl.vertexAttribPointer(m_posLoc, NUM_COMPONENTS, GL_FLOAT, false, 0, DE_NULL),
		gl.getError());
	gl.bindVertexArray(0);
	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
	GLU_CHECK_ERROR(gl.getError());
}

class VertexArrayBinder : public SimpleBinder
{
public:
						VertexArrayBinder	(lt::Context& ctx)
							: SimpleBinder	(ctx, 0, GL_NONE, GL_VERTEX_ARRAY_BINDING, true) {}
	void				bind			(GLuint name) { glBindVertexArray(name); }
};

class SamplerBinder : public Binder
{
public:
						SamplerBinder	(lt::Context& ctx) : Binder(ctx) {}
	void				bind			(GLuint name) { glBindSampler(0, name); }
	GLuint				getBinding		(void)
	{
		GLint arr[32] = {};
		glGetIntegerv(GL_SAMPLER_BINDING, arr);
		log() << TestLog::Message << "// First output integer: " << arr[0]
			  << TestLog::EndMessage;
		return arr[0];
	}
	bool				genRequired		(void) const { return true; }
};

class QueryBinder : public Binder
{
public:
						QueryBinder		(lt::Context& ctx) : Binder(ctx) {}
	void				bind			(GLuint name)
	{
		if (name != 0)
			glBeginQuery(GL_ANY_SAMPLES_PASSED, name);
		else
			glEndQuery(GL_ANY_SAMPLES_PASSED);
	}
	GLuint				getBinding		(void) { return 0; }
};

class BufferVAOAttacher : public Attacher
{
public:
						BufferVAOAttacher	(lt::Context& ctx, Type& elementType,
											 Type& varrType, ScaleProgram& program)
							: Attacher		(ctx, elementType, varrType)
							, m_program		(program) {}
	void				initAttachment		(GLuint seed, GLuint element);
	void				attach				(GLuint element, GLuint container);
	void				detach				(GLuint element, GLuint container);
	bool				canAttachDeleted	(void) const { return false; }
	ScaleProgram&		getProgram			(void) { return m_program; }
	GLuint				getAttachment		(GLuint container);

private:
	ScaleProgram&		m_program;
};

static const GLfloat s_varrData[NUM_VERTICES * NUM_COMPONENTS] =
{
	-1.0,  0.0, 0.0, 1.0,
	 1.0,  1.0, 0.0, 1.0,
	 0.0, -1.0, 0.0, 1.0
};

void initBuffer (const Functions& gl, GLuint seed, GLenum usage, GLuint buffer)
{
	gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
	if (seed == 0)
		gl.bufferData(GL_ARRAY_BUFFER, sizeof(s_varrData), s_varrData, usage);
	else
	{
		Random	rnd	(seed);
		GLfloat data[DE_LENGTH_OF_ARRAY(s_varrData)];

		for (int ndx = 0; ndx < NUM_VERTICES; ndx++)
		{
			GLfloat* vertex = &data[ndx * NUM_COMPONENTS];
			vertex[0] = 2.0f * (rnd.getFloat() - 0.5f);
			vertex[1] = 2.0f * (rnd.getFloat() - 0.5f);
			DE_STATIC_ASSERT(NUM_COMPONENTS == 4);
			vertex[2] = 0.0f;
			vertex[3] = 1.0f;
		}
		gl.bufferData(GL_ARRAY_BUFFER, sizeof(data), data, usage);
	}
	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
	GLU_CHECK_ERROR(gl.getError());
}

void BufferVAOAttacher::initAttachment (GLuint seed, GLuint buffer)
{
	initBuffer(gl(), seed, GL_STATIC_DRAW, buffer);
	log() << TestLog::Message << "// Initialized buffer " << buffer << " from seed " << seed
		  << TestLog::EndMessage;
}

void BufferVAOAttacher::attach (GLuint buffer, GLuint vao)
{
	m_program.setPos(buffer, vao);
	log() << TestLog::Message
		  << "// Set the `pos` attribute in VAO " << vao << " to buffer " << buffer
		  << TestLog::EndMessage;
}

void BufferVAOAttacher::detach (GLuint buffer, GLuint varr)
{
	DE_UNREF(buffer);
	attach(0, varr);
}

GLuint BufferVAOAttacher::getAttachment (GLuint varr)
{
	GLint name = 0;
	gl().bindVertexArray(varr);
	gl().getVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &name);
	gl().bindVertexArray(0);
	GLU_CHECK_ERROR(gl().getError());
	return GLuint(name);
}

class BufferVAOInputAttacher : public InputAttacher
{
public:
						BufferVAOInputAttacher	(BufferVAOAttacher& attacher)
							: InputAttacher		(attacher)
							, m_program			(attacher.getProgram()) {}
	void				drawContainer			(GLuint container, Surface& dst);

private:
	ScaleProgram&		m_program;
};

void BufferVAOInputAttacher::drawContainer (GLuint vao, Surface& dst)
{
	m_program.draw(vao, 1.0, false, &dst);
	log() << TestLog::Message << "// Drew an output image with VAO " << vao
		  << TestLog::EndMessage;
};

class BufferTfAttacher : public Attacher
{
public:
				BufferTfAttacher	(lt::Context& ctx, Type& bufferType, Type& tfType)
					: Attacher		(ctx, bufferType, tfType) {}
	void		initAttachment		(GLuint seed, GLuint element);
	void		attach				(GLuint buffer, GLuint tf);
	void		detach				(GLuint buffer, GLuint tf);
	bool		canAttachDeleted	(void) const { return false; }
	GLuint		getAttachment		(GLuint tf);
};

void BufferTfAttacher::initAttachment (GLuint seed, GLuint buffer)
{
	initBuffer(gl(), seed, GL_DYNAMIC_READ, buffer);
	log() << TestLog::Message << "// Initialized buffer " << buffer << " from seed " << seed
		  << TestLog::EndMessage;
}

void BufferTfAttacher::attach (GLuint buffer, GLuint tf)
{
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf);
	glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
	GLU_CHECK_ERROR(gl().getError());
}

void BufferTfAttacher::detach (GLuint buffer, GLuint tf)
{
	DE_UNREF(buffer);
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf);
	glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
	GLU_CHECK_ERROR(gl().getError());
}

GLuint BufferTfAttacher::getAttachment (GLuint tf)
{
	GLint ret = 0;
	gl().bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf);
	gl().getIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, &ret);
	gl().bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
	GLU_CHECK_ERROR(gl().getError());
	return GLuint(ret);
}

class BufferTfOutputAttacher : public OutputAttacher
{
public:
				BufferTfOutputAttacher	(BufferTfAttacher&	attacher, ScaleProgram& program)
					: OutputAttacher	(attacher)
					, m_program			(program) {}
	void		setupContainer		(GLuint seed, GLuint container);
	void		drawAttachment		(GLuint attachment, Surface& dst);

private:
	ScaleProgram&	m_program;
};

void BufferTfOutputAttacher::drawAttachment (GLuint buffer, Surface& dst)
{
	VertexArray vao(getRenderContext());

	m_program.setPos(buffer, *vao);
	m_program.draw(*vao, 1.0, false, &dst);
	log() << TestLog::Message
		  << "// Drew output image with vertices from buffer " << buffer
		  << TestLog::EndMessage;
	GLU_CHECK_ERROR(gl().getError());
}

void BufferTfOutputAttacher::setupContainer (GLuint seed, GLuint tf)
{
	Buffer		posBuf	(getRenderContext());
	VertexArray	vao		(getRenderContext());

	initBuffer(gl(), seed, GL_STATIC_DRAW, *posBuf);
	m_program.setPos(*posBuf, *vao);

	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf);
	m_program.draw(*vao, -1.0, true, DE_NULL);
	log() << TestLog::Message
		  << "// Drew an image with seed " << seed << " with transform feedback to " << tf
		  << TestLog::EndMessage;
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
	GLU_CHECK_ERROR(gl().getError());
}

class ES3Types : public ES2Types
{
public:
							ES3Types		(lt::Context& ctx);
private:
	ScaleProgram			m_program;
	QueryBinder				m_queryBind;
	SimpleType				m_queryType;
	SimpleBinder			m_tfBind;
	SimpleType				m_tfType;
	VertexArrayBinder		m_varrBind;
	SimpleType				m_varrType;
	SamplerBinder			m_samplerBind;
	SimpleType				m_samplerType;
	BufferVAOAttacher		m_bufVarrAtt;
	BufferVAOInputAttacher	m_bufVarrInAtt;
	BufferTfAttacher		m_bufTfAtt;
	BufferTfOutputAttacher	m_bufTfOutAtt;
};

ES3Types::ES3Types (lt::Context& ctx)
	: ES2Types		(ctx)
	, m_program		(ctx)
	, m_queryBind	(ctx)
	, m_queryType	(ctx, "query", &CallLogWrapper::glGenQueries,
					 &CallLogWrapper::glDeleteQueries,
					 &CallLogWrapper::glIsQuery, &m_queryBind)
	, m_tfBind		(ctx, &CallLogWrapper::glBindTransformFeedback, GL_TRANSFORM_FEEDBACK,
					 GL_TRANSFORM_FEEDBACK_BINDING, true)
	, m_tfType		(ctx, "transform_feedback", &CallLogWrapper::glGenTransformFeedbacks,
					 &CallLogWrapper::glDeleteTransformFeedbacks,
					 &CallLogWrapper::glIsTransformFeedback, &m_tfBind)
	, m_varrBind	(ctx)
	, m_varrType	(ctx, "vertex_array", &CallLogWrapper::glGenVertexArrays,
					 &CallLogWrapper::glDeleteVertexArrays,
					 &CallLogWrapper::glIsVertexArray, &m_varrBind)
	, m_samplerBind	(ctx)
	, m_samplerType	(ctx, "sampler", &CallLogWrapper::glGenSamplers,
					 &CallLogWrapper::glDeleteSamplers,
					 &CallLogWrapper::glIsSampler, &m_samplerBind, true)
	, m_bufVarrAtt	(ctx, m_bufferType, m_varrType, m_program)
	, m_bufVarrInAtt(m_bufVarrAtt)
	, m_bufTfAtt	(ctx, m_bufferType, m_tfType)
	, m_bufTfOutAtt	(m_bufTfAtt, m_program)
{
	Type* types[] = { &m_queryType, &m_tfType, &m_varrType, &m_samplerType };
	m_types.insert(m_types.end(), DE_ARRAY_BEGIN(types), DE_ARRAY_END(types));

	m_attachers.push_back(&m_bufVarrAtt);
	m_attachers.push_back(&m_bufTfAtt);

	m_inAttachers.push_back(&m_bufVarrInAtt);
	m_outAttachers.push_back(&m_bufTfOutAtt);
}

class TfDeleteActiveTest : public TestCase, private CallLogWrapper
{
	public:
						TfDeleteActiveTest	(gles3::Context& context,
											 const char* name, const char* description);
	IterateResult		iterate				(void);
};

TfDeleteActiveTest::TfDeleteActiveTest (gles3::Context& context,
										const char* name, const char* description)
	: TestCase			(context, name, description)
	, CallLogWrapper	(context.getRenderContext().getFunctions(),
						 context.getTestContext().getLog())
{
	enableLogging(true);
}

class ScopedTransformFeedbackFeedback
{
public:
							ScopedTransformFeedbackFeedback		(glu::CallLogWrapper& gl, GLenum type);
							~ScopedTransformFeedbackFeedback	(void);

private:
	glu::CallLogWrapper&	m_gl;
};

ScopedTransformFeedbackFeedback::ScopedTransformFeedbackFeedback (glu::CallLogWrapper& gl, GLenum type)
	: m_gl(gl)
{
	m_gl.glBeginTransformFeedback(type);
	GLU_EXPECT_NO_ERROR(m_gl.glGetError(), "glBeginTransformFeedback");
}

ScopedTransformFeedbackFeedback::~ScopedTransformFeedbackFeedback (void)
{
	m_gl.glEndTransformFeedback();
}

IterateResult TfDeleteActiveTest::iterate (void)
{
	static const char* const s_xfbVertexSource =	"#version 300 es\n"
													"void main ()\n"
													"{\n"
													"	gl_Position = vec4(float(gl_VertexID) / 2.0, float(gl_VertexID % 2) / 2.0, 0.0, 1.0);\n"
													"}\n";
	static const char* const s_xfbFragmentSource =	"#version 300 es\n"
													"layout(location=0) out mediump vec4 dEQP_FragColor;\n"
													"void main ()\n"
													"{\n"
													"	dEQP_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
													"}\n";

	glu::Buffer			buf			(m_context.getRenderContext());
	GLuint				tf			= 0;
	glu::ShaderProgram	program		(m_context.getRenderContext(),
									 glu::ProgramSources()
										<< glu::VertexSource(s_xfbVertexSource)
										<< glu::FragmentSource(s_xfbFragmentSource)
										<< glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS)
										<< glu::TransformFeedbackVarying("gl_Position"));

	if (!program.isOk())
	{
		m_testCtx.getLog() << program;
		throw tcu::TestError("failed to build program");
	}

	try
	{
		GLU_CHECK_CALL(glUseProgram(program.getProgram()));
		GLU_CHECK_CALL(glGenTransformFeedbacks(1, &tf));
		GLU_CHECK_CALL(glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tf));
		GLU_CHECK_CALL(glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, *buf));
		GLU_CHECK_CALL(glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 3 * sizeof(glw::GLfloat[4]), DE_NULL, GL_DYNAMIC_COPY));

		{
			ScopedTransformFeedbackFeedback xfb(static_cast<glu::CallLogWrapper&>(*this), GL_TRIANGLES);

			glDeleteTransformFeedbacks(1, &tf);
			{
				GLenum err = glGetError();
				if (err != GL_INVALID_OPERATION)
					getTestContext().setTestResult(
						QP_TEST_RESULT_FAIL,
						"Deleting active transform feedback did not produce GL_INVALID_OPERATION");
				else
					getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
			}
		}
		GLU_CHECK(); // ScopedTransformFeedbackFeedback::dtor might modify error state

		GLU_CHECK_CALL(glDeleteTransformFeedbacks(1, &tf));
	}
	catch (const glu::Error&)
	{
		glDeleteTransformFeedbacks(1, &tf);
		throw;
	}

	return STOP;
}

class TestGroup : public TestCaseGroup
{
public:
							TestGroup		(gles3::Context& context)
								: TestCaseGroup	(context, "lifetime", "Object lifetime tests")
							{}
	void					init			(void);
private:
	MovePtr<Types>			m_types;
};

void TestGroup::init (void)
{
	gles3::Context&	ctx		= getContext();
	lt::Context		ltCtx	(ctx.getRenderContext(), ctx.getTestContext());

	m_types	= MovePtr<Types>(new ES3Types(ltCtx));

	addTestCases(*this, *m_types);

	TestCaseGroup* deleteActiveGroup =
		new TestCaseGroup(ctx, "delete_active", "Delete active object");
	addChild(deleteActiveGroup);
	deleteActiveGroup->addChild(
		new TfDeleteActiveTest(ctx, "transform_feedback", "Transform Feedback"));
}

} // anonymous

TestCaseGroup* createLifetimeTests (Context& context)
{
	return new TestGroup(context);
}

} // Functional
} // gles3
} // deqp
