/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 2.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 Flush and finish tests.
 *//*--------------------------------------------------------------------*/

#include "es2fFlushFinishTests.hpp"

#include "gluRenderContext.hpp"
#include "gluObjectWrapper.hpp"
#include "gluShaderProgram.hpp"
#include "gluDrawUtil.hpp"

#include "glsCalibration.hpp"

#include "tcuTestLog.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuCPUWarmup.hpp"

#include "glwEnums.hpp"
#include "glwFunctions.hpp"

#include "deRandom.hpp"
#include "deStringUtil.hpp"
#include "deClock.h"
#include "deThread.h"
#include "deMath.h"

#include <algorithm>

namespace deqp
{
namespace gles2
{
namespace Functional
{

using std::vector;
using std::string;
using tcu::TestLog;
using tcu::Vec2;
using deqp::gls::theilSenLinearRegression;
using deqp::gls::LineParameters;

namespace
{

enum
{
	MAX_VIEWPORT_SIZE		= 128,
	MAX_SAMPLE_DURATION_US	= 1000*1000,
	WAIT_TIME_MS			= 1200,
	NUM_SAMPLES				= 25,
	MIN_DRAW_CALL_COUNT		= 10,
	MAX_DRAW_CALL_COUNT		= 1<<20,
	NUM_ITERS_IN_SHADER		= 10
};

const float		NO_CORR_COEF_THRESHOLD		= 0.1f;
const float		FLUSH_COEF_THRESHOLD		= 0.2f;
const float		CORRELATED_COEF_THRESHOLD	= 0.5f;

static void busyWait (int milliseconds)
{
	const deUint64	startTime	= deGetMicroseconds();
	float			v			= 2.0f;

	for (;;)
	{
		for (int i = 0; i < 10; i++)
			v = deFloatSin(v);

		if (deGetMicroseconds()-startTime >= deUint64(1000*milliseconds))
			break;
	}
}

class CalibrationFailedException : public std::runtime_error
{
public:
	CalibrationFailedException (const std::string& reason) : std::runtime_error(reason) {}
};

class FlushFinishCase : public TestCase
{
public:
	enum ExpectedBehavior
	{
		EXPECT_COEF_LESS_THAN = 0,
		EXPECT_COEF_GREATER_THAN,
	};

							FlushFinishCase		(Context&			context,
												 const char*		name,
												 const char*		description,
												 ExpectedBehavior	waitBehavior,
												 float				waitThreshold,
												 ExpectedBehavior	readBehavior,
												 float				readThreshold);
							~FlushFinishCase	(void);

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

	struct Sample
	{
		int			numDrawCalls;
		deUint64	waitTime;
		deUint64	readPixelsTime;
	};

	struct CalibrationParams
	{
		int			maxDrawCalls;
	};

protected:
	virtual void			waitForGL			(void) = 0;

private:
							FlushFinishCase		(const FlushFinishCase&);
	FlushFinishCase&		operator=			(const FlushFinishCase&);

	CalibrationParams		calibrate			(void);
	void					analyzeResults		(const std::vector<Sample>& samples, const CalibrationParams& calibrationParams);

	void					setupRenderState	(void);
	void					render				(int numDrawCalls);
	void					readPixels			(void);

	const ExpectedBehavior	m_waitBehavior;
	const float				m_waitThreshold;
	const ExpectedBehavior	m_readBehavior;
	const float				m_readThreshold;

	glu::ShaderProgram*		m_program;
};

FlushFinishCase::FlushFinishCase (Context& context, const char* name, const char* description, ExpectedBehavior waitBehavior, float waitThreshold, ExpectedBehavior readBehavior, float readThreshold)
	: TestCase			(context, name, description)
	, m_waitBehavior	(waitBehavior)
	, m_waitThreshold	(waitThreshold)
	, m_readBehavior	(readBehavior)
	, m_readThreshold	(readThreshold)
	, m_program			(DE_NULL)
{
}

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

void FlushFinishCase::init (void)
{
	DE_ASSERT(!m_program);

	m_program = new glu::ShaderProgram(m_context.getRenderContext(),
		glu::ProgramSources()
			<< glu::VertexSource(
				"attribute highp vec4 a_position;\n"
				"varying highp vec4 v_coord;\n"
				"void main (void)\n"
				"{\n"
				"	gl_Position = a_position;\n"
				"	v_coord = a_position;\n"
				"}\n")
			<< glu::FragmentSource(
				"uniform mediump int u_numIters;\n"
				"varying mediump vec4 v_coord;\n"
				"void main (void)\n"
				"{\n"
				"	highp vec4 color = v_coord;\n"
				"	for (int i = 0; i < " + de::toString(int(NUM_ITERS_IN_SHADER)) + "; i++)\n"
				"		color = sin(color);\n"
				"	gl_FragColor = color;\n"
				"}\n"));

	if (!m_program->isOk())
	{
		m_testCtx.getLog() << *m_program;
		delete m_program;
		m_program = DE_NULL;
		TCU_FAIL("Compile failed");
	}
}

void FlushFinishCase::deinit (void)
{
	delete m_program;
	m_program = DE_NULL;
}

tcu::TestLog& operator<< (tcu::TestLog& log, const FlushFinishCase::Sample& sample)
{
	log << TestLog::Message << sample.numDrawCalls << " calls:\t" << sample.waitTime << " us wait,\t" << sample.readPixelsTime << " us read" << TestLog::EndMessage;
	return log;
}

void FlushFinishCase::setupRenderState (void)
{
	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
	const int				posLoc			= gl.getAttribLocation(m_program->getProgram(), "a_position");
	const int				viewportW		= de::min<int>(m_context.getRenderTarget().getWidth(), MAX_VIEWPORT_SIZE);
	const int				viewportH		= de::min<int>(m_context.getRenderTarget().getHeight(), MAX_VIEWPORT_SIZE);

	static const float s_positions[] =
	{
		-1.0f, -1.0f,
		+1.0f, -1.0f,
		-1.0f, +1.0f,
		+1.0f, +1.0f
	};

	TCU_CHECK(posLoc >= 0);

	gl.viewport(0, 0, viewportW, viewportH);
	gl.useProgram(m_program->getProgram());
	gl.enableVertexAttribArray(posLoc);
	gl.vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, &s_positions[0]);
	gl.enable(GL_BLEND);
	gl.blendFunc(GL_ONE, GL_ONE);
	gl.blendEquation(GL_FUNC_ADD);
	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up render state");
}

void FlushFinishCase::render (int numDrawCalls)
{
	const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();

	const deUint8 indices[] = { 0, 1, 2, 2, 1, 3 };

	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	for (int ndx = 0; ndx < numDrawCalls; ndx++)
		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_BYTE, &indices[0]);
}

void FlushFinishCase::readPixels (void)
{
	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
	deUint8					tmp[4];

	gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &tmp);
}

FlushFinishCase::CalibrationParams FlushFinishCase::calibrate (void)
{
	tcu::ScopedLogSection		section				(m_testCtx.getLog(), "CalibrationInfo", "Calibration info");
	CalibrationParams			params;

	// Find draw call count that results in desired maximum time.
	{
		deUint64			prevDuration			= 0;
		int					prevDrawCount			= 1;
		int					curDrawCount			= 1;

		m_testCtx.getLog() << TestLog::Message << "Calibrating maximum draw call count, target duration = " << int(MAX_SAMPLE_DURATION_US) << " us" << TestLog::EndMessage;

		for (;;)
		{
			deUint64 curDuration;

			{
				const deUint64	startTime	= deGetMicroseconds();
				render(curDrawCount);
				readPixels();
				curDuration = deGetMicroseconds()-startTime;
			}

			m_testCtx.getLog() << TestLog::Message << "Duration with " << curDrawCount << " draw calls = " << curDuration << " us" << TestLog::EndMessage;

			if (curDuration > MAX_SAMPLE_DURATION_US)
			{
				if (curDrawCount > 1)
				{
					// Compute final count by using linear estimation.
					const float		a		= float(curDuration - prevDuration) / float(curDrawCount - prevDrawCount);
					const float		b		= float(prevDuration) - a*float(prevDrawCount);
					const float		est		= (float(MAX_SAMPLE_DURATION_US) - b) / a;

					curDrawCount = de::clamp(deFloorFloatToInt32(est), 1, int(MAX_DRAW_CALL_COUNT));
				}
				// else: Settle on 1.

				break;
			}
			else if (curDrawCount >= MAX_DRAW_CALL_COUNT)
				break; // Settle on maximum.
			else
			{
				prevDrawCount	= curDrawCount;
				prevDuration	= curDuration;
				curDrawCount	= curDrawCount*2;
			}
		}

		params.maxDrawCalls = curDrawCount;

		m_testCtx.getLog() << TestLog::Integer("MaxDrawCalls", "Maximum number of draw calls", "", QP_KEY_TAG_NONE, params.maxDrawCalls);
	}

	// Sanity check.
	if (params.maxDrawCalls < MIN_DRAW_CALL_COUNT)
		throw CalibrationFailedException("Calibration failed, maximum draw call count is too low");

	return params;
}

struct CompareSampleDrawCount
{
	bool operator() (const FlushFinishCase::Sample& a, const FlushFinishCase::Sample& b) const { return a.numDrawCalls < b.numDrawCalls; }
};

std::vector<Vec2> getPointsFromSamples (const std::vector<FlushFinishCase::Sample>& samples, const deUint64 FlushFinishCase::Sample::*field)
{
	vector<Vec2> points(samples.size());

	for (size_t ndx = 0; ndx < samples.size(); ndx++)
		points[ndx] = Vec2(float(samples[ndx].numDrawCalls), float(samples[ndx].*field));

	return points;
}

template<typename T>
T getMaximumValue (const std::vector<FlushFinishCase::Sample>& samples, const T FlushFinishCase::Sample::*field)
{
	DE_ASSERT(!samples.empty());

	T maxVal = samples[0].*field;

	for (size_t ndx = 1; ndx < samples.size(); ndx++)
		maxVal = de::max(maxVal, samples[ndx].*field);

	return maxVal;
}

void FlushFinishCase::analyzeResults (const std::vector<Sample>& samples, const CalibrationParams& calibrationParams)
{
	const vector<Vec2>		waitTimes		= getPointsFromSamples(samples, &Sample::waitTime);
	const vector<Vec2>		readTimes		= getPointsFromSamples(samples, &Sample::readPixelsTime);
	const LineParameters	waitLine		= theilSenLinearRegression(waitTimes);
	const LineParameters	readLine		= theilSenLinearRegression(readTimes);
	const float				normWaitCoef	= waitLine.coefficient * float(calibrationParams.maxDrawCalls) / float(MAX_SAMPLE_DURATION_US);
	const float				normReadCoef	= readLine.coefficient * float(calibrationParams.maxDrawCalls) / float(MAX_SAMPLE_DURATION_US);
	bool					allOk			= true;

	{
		tcu::ScopedLogSection	section			(m_testCtx.getLog(), "Samples", "Samples");
		vector<Sample>			sortedSamples	(samples.begin(), samples.end());

		std::sort(sortedSamples.begin(), sortedSamples.end(), CompareSampleDrawCount());

		for (vector<Sample>::const_iterator iter = sortedSamples.begin(); iter != sortedSamples.end(); ++iter)
			m_testCtx.getLog() << *iter;
	}

	m_testCtx.getLog() << TestLog::Float("WaitCoefficient",				"Wait coefficient", "", QP_KEY_TAG_NONE, waitLine.coefficient)
					   << TestLog::Float("ReadCoefficient",				"Read coefficient", "", QP_KEY_TAG_NONE, readLine.coefficient)
					   << TestLog::Float("NormalizedWaitCoefficient",	"Normalized wait coefficient", "", QP_KEY_TAG_NONE, normWaitCoef)
					   << TestLog::Float("NormalizedReadCoefficient",	"Normalized read coefficient", "", QP_KEY_TAG_NONE, normReadCoef);

	{
		const bool		waitCorrelated		= normWaitCoef > CORRELATED_COEF_THRESHOLD;
		const bool		readCorrelated		= normReadCoef > CORRELATED_COEF_THRESHOLD;
		const bool		waitNotCorr			= normWaitCoef < NO_CORR_COEF_THRESHOLD;
		const bool		readNotCorr			= normReadCoef < NO_CORR_COEF_THRESHOLD;

		if (waitCorrelated || waitNotCorr)
			m_testCtx.getLog() << TestLog::Message << "Wait time is" << (waitCorrelated ? "" : " NOT") << " correlated to rendering workload size." << TestLog::EndMessage;
		else
			m_testCtx.getLog() << TestLog::Message << "Warning: Wait time correlation to rendering workload size is unclear." << TestLog::EndMessage;

		if (readCorrelated || readNotCorr)
			m_testCtx.getLog() << TestLog::Message << "Read time is" << (readCorrelated ? "" : " NOT") << " correlated to rendering workload size." << TestLog::EndMessage;
		else
			m_testCtx.getLog() << TestLog::Message << "Warning: Read time correlation to rendering workload size is unclear." << TestLog::EndMessage;
	}

	for (int ndx = 0; ndx < 2; ndx++)
	{
		const float				coef		= ndx == 0 ? normWaitCoef : normReadCoef;
		const char*				name		= ndx == 0 ? "wait" : "read";
		const ExpectedBehavior	behavior	= ndx == 0 ? m_waitBehavior : m_readBehavior;
		const float				threshold	= ndx == 0 ? m_waitThreshold : m_readThreshold;
		const bool				isOk		= behavior == EXPECT_COEF_GREATER_THAN	? coef > threshold :
											  behavior == EXPECT_COEF_LESS_THAN		? coef < threshold : false;
		const char*				cmpName		= behavior == EXPECT_COEF_GREATER_THAN	? "greater than" :
											  behavior == EXPECT_COEF_LESS_THAN		? "less than" : DE_NULL;

		if (!isOk)
		{
			m_testCtx.getLog() << TestLog::Message << "ERROR: Expected " << name << " coefficient to be " << cmpName << " " << threshold << TestLog::EndMessage;
			allOk = false;
		}
	}

	m_testCtx.setTestResult(allOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_COMPATIBILITY_WARNING,
							allOk ? "Pass"				: "Suspicious performance behavior");
}

FlushFinishCase::IterateResult FlushFinishCase::iterate (void)
{
	vector<Sample>		samples		(NUM_SAMPLES);
	CalibrationParams	params;

	tcu::warmupCPU();

	setupRenderState();

	// Do one full render cycle.
	{
		render(1);
		readPixels();
	}

	// Calibrate.
	try
	{
		params = calibrate();
	}
	catch (const CalibrationFailedException& e)
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, e.what());
		return STOP;
	}

	// Do measurement.
	{
		de::Random	rnd		(123);

		for (size_t ndx = 0; ndx < samples.size(); ndx++)
		{
			const int	drawCallCount	= rnd.getInt(1, params.maxDrawCalls);
			deUint64	waitStartTime;
			deUint64	readStartTime;
			deUint64	readFinishTime;

			render(drawCallCount);

			waitStartTime = deGetMicroseconds();
			waitForGL();

			readStartTime = deGetMicroseconds();
			readPixels();
			readFinishTime = deGetMicroseconds();

			samples[ndx].numDrawCalls	= drawCallCount;
			samples[ndx].waitTime		= readStartTime-waitStartTime;
			samples[ndx].readPixelsTime	= readFinishTime-readStartTime;

			if (m_testCtx.getWatchDog())
				qpWatchDog_touch(m_testCtx.getWatchDog());
		}
	}

	// Analyze - sets test case result.
	analyzeResults(samples, params);

	return STOP;
}

class WaitOnlyCase : public FlushFinishCase
{
public:
	WaitOnlyCase (Context& context)
		: FlushFinishCase(context, "wait", "Wait only", EXPECT_COEF_LESS_THAN, NO_CORR_COEF_THRESHOLD, EXPECT_COEF_GREATER_THAN, -1000.0f /* practically nothing is expected */)
	{
	}

	void init (void)
	{
		m_testCtx.getLog() << TestLog::Message << int(WAIT_TIME_MS) << " ms busy wait" << TestLog::EndMessage;
		FlushFinishCase::init();
	}

protected:
	void waitForGL (void)
	{
		busyWait(WAIT_TIME_MS);
	}
};

class FlushOnlyCase : public FlushFinishCase
{
public:
	FlushOnlyCase (Context& context)
		: FlushFinishCase(context, "flush", "Flush only", EXPECT_COEF_LESS_THAN, FLUSH_COEF_THRESHOLD, EXPECT_COEF_GREATER_THAN, CORRELATED_COEF_THRESHOLD)
	{
	}

	void init (void)
	{
		m_testCtx.getLog() << TestLog::Message << "Single call to glFlush()" << TestLog::EndMessage;
		FlushFinishCase::init();
	}

protected:
	void waitForGL (void)
	{
		m_context.getRenderContext().getFunctions().flush();
	}
};

class FlushWaitCase : public FlushFinishCase
{
public:
	FlushWaitCase (Context& context)
		: FlushFinishCase(context, "flush_wait", "Wait after flushing", EXPECT_COEF_LESS_THAN, FLUSH_COEF_THRESHOLD, EXPECT_COEF_LESS_THAN, NO_CORR_COEF_THRESHOLD)
	{
	}

	void init (void)
	{
		m_testCtx.getLog() << TestLog::Message << "glFlush() followed by " << int(WAIT_TIME_MS) << " ms busy wait" << TestLog::EndMessage;
		FlushFinishCase::init();
	}

protected:
	void waitForGL (void)
	{
		m_context.getRenderContext().getFunctions().flush();
		busyWait(WAIT_TIME_MS);
	}
};

class FinishOnlyCase : public FlushFinishCase
{
public:
	FinishOnlyCase (Context& context)
		: FlushFinishCase(context, "finish", "Finish only", EXPECT_COEF_GREATER_THAN, CORRELATED_COEF_THRESHOLD, EXPECT_COEF_LESS_THAN, NO_CORR_COEF_THRESHOLD)
	{
	}

	void init (void)
	{
		m_testCtx.getLog() << TestLog::Message << "Single call to glFinish()" << TestLog::EndMessage;
		FlushFinishCase::init();
	}

protected:
	void waitForGL (void)
	{
		m_context.getRenderContext().getFunctions().finish();
	}
};

class FinishWaitCase : public FlushFinishCase
{
public:
	FinishWaitCase (Context& context)
		: FlushFinishCase(context, "finish_wait", "Finish and wait", EXPECT_COEF_GREATER_THAN, CORRELATED_COEF_THRESHOLD, EXPECT_COEF_LESS_THAN, NO_CORR_COEF_THRESHOLD)
	{
	}

	void init (void)
	{
		m_testCtx.getLog() << TestLog::Message << "glFinish() followed by " << int(WAIT_TIME_MS) << " ms busy wait" << TestLog::EndMessage;
		FlushFinishCase::init();
	}

protected:
	void waitForGL (void)
	{
		m_context.getRenderContext().getFunctions().finish();
		busyWait(WAIT_TIME_MS);
	}
};

} // anonymous

FlushFinishTests::FlushFinishTests (Context& context)
	: TestCaseGroup(context, "flush_finish", "Flush and Finish tests")
{
}

FlushFinishTests::~FlushFinishTests (void)
{
}

void FlushFinishTests::init (void)
{
	addChild(new WaitOnlyCase	(m_context));
	addChild(new FlushOnlyCase	(m_context));
	addChild(new FlushWaitCase	(m_context));
	addChild(new FinishOnlyCase	(m_context));
	addChild(new FinishWaitCase	(m_context));
}

} // Functional
} // gles2
} // deqp
