/*-------------------------------------------------------------------------
 * drawElements Quality Program EGL Module
 * ---------------------------------------
 *
 * Copyright 2017 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 Test the EGL_ANDROID_get_frame_timestamps extension.
 *//*--------------------------------------------------------------------*/

#include "teglGetFrameTimestampsTests.hpp"

#include "teglSimpleConfigCase.hpp"

#include "egluNativeWindow.hpp"
#include "egluUtil.hpp"
#include "egluUnique.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"

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

#include "tcuResultCollector.hpp"
#include "tcuTestLog.hpp"
#include "tcuSurface.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuVector.hpp"
#include "tcuVectorUtil.hpp"

#include "deClock.h"
#include "deMath.h"
#include "deUniquePtr.hpp"
#include "deThread.hpp"

#include <algorithm>
#include <string>
#include <vector>
#include <sstream>

// Tentative EGL header definitions for EGL_ANDROID_get_Frame_timestamps.
// \todo [2017-01-25 brianderson] Remove once defined in the official headers.
#define EGL_TIMESTAMPS_ANDROID 0x3430
#define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
#define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
#define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
#define EGL_READS_DONE_TIME_ANDROID 0x343C
typedef deInt64 EGLnsecsANDROID;
typedef deUint64 EGLuint64KHR;
#define EGL_TIMESTAMP_PENDING_ANDROID (-2)
#define EGL_TIMESTAMP_INVALID_ANDROID (-1)
typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetNextFrameIdANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR *frameId);
typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint numTimestamps, const eglw::EGLint *names, EGLnsecsANDROID *values);
typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint name);
typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampsANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR frameId, eglw::EGLint numTimestamps, const eglw::EGLint *timestamps, EGLnsecsANDROID *values);
typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint timestamp);

#define CHECK_NAKED_EGL_CALL(EGLW, CALL)	do { CALL; eglu::checkError((EGLW).getError(), #CALL, __FILE__, __LINE__); } while (deGetFalse())

namespace deqp
{
namespace egl
{

using tcu::TestLog;
using std::string;
using std::vector;
using namespace eglw;

namespace
{

// Careful: This has microsecond precision, which can cause timestamps to
// appear non monotonic when compared to the nanosecond precision timestamps
// we get from the eglGetFrameTimestamps extension.
// Current test expectations only make sure microsecond precision timestamps
// are less than the nanosecond precision timestamps, so this is okay.
EGLnsecsANDROID getNanoseconds (void)
{
	return deGetMicroseconds() * 1000;
}

struct FrameTimes
{
	FrameTimes (void)
		: frameId						(-1)
		, swapBufferBeginNs				(-1)
		, compositeDeadline				(-1)
		, compositeInterval				(-1)
		, compositeToPresentLatency		(-1)
		, requestedPresent				(-1)
		, latch							(-1)
		, firstCompositionStart			(-1)
		, lastCompositionStart			(-1)
		, dequeueReady					(-1)
		, renderingComplete				(-1)
		, firstCompositionGpuFinished	(-1)
		, displayPresent				(-1)
		, readsDone						(-1)
	{
	}

	EGLuint64KHR	frameId;

	// Timestamps sampled by the test.
	EGLnsecsANDROID	swapBufferBeginNs;

	// Compositor info.
	EGLnsecsANDROID	compositeDeadline;
	EGLnsecsANDROID	compositeInterval;
	EGLnsecsANDROID	compositeToPresentLatency;

	// CPU Timeline.
	EGLnsecsANDROID	requestedPresent;
	EGLnsecsANDROID	latch;
	EGLnsecsANDROID	firstCompositionStart;
	EGLnsecsANDROID	lastCompositionStart;
	EGLnsecsANDROID	dequeueReady;

	// GPU Timeline.
	EGLnsecsANDROID	renderingComplete;
	EGLnsecsANDROID	firstCompositionGpuFinished;
	EGLnsecsANDROID	displayPresent;
	EGLnsecsANDROID	readsDone;
};


struct TimestampInfo
{
	TimestampInfo()
		: required(false)
		, supported(false)
		, supportedIndex(0)
	{
	}

	TimestampInfo(bool required_, bool supported_, size_t supportedIndex_)
		: required(required_)
		, supported(supported_)
		, supportedIndex(supportedIndex_)
	{
	}

	bool	required;
	bool	supported;
	size_t	supportedIndex;
};

typedef std::map<eglw::EGLint, TimestampInfo> TimestampInfoMap;

EGLnsecsANDROID getTimestamp(eglw::EGLint name, TimestampInfoMap& map, const std::vector<EGLnsecsANDROID>& supportedValues)
{
	TimestampInfo& info = map[name];
	return info.supported ? supportedValues[info.supportedIndex] : EGL_TIMESTAMP_INVALID_ANDROID;
}

void populateFrameTimes(FrameTimes* frameTimes, TimestampInfoMap& map, const std::vector<EGLnsecsANDROID>& supportedValues)
{
	frameTimes->requestedPresent			=	getTimestamp(EGL_REQUESTED_PRESENT_TIME_ANDROID, map, supportedValues);
	frameTimes->renderingComplete			=	getTimestamp(EGL_RENDERING_COMPLETE_TIME_ANDROID, map, supportedValues);
	frameTimes->latch						=	getTimestamp(EGL_COMPOSITION_LATCH_TIME_ANDROID, map, supportedValues);
	frameTimes->firstCompositionStart		=	getTimestamp(EGL_FIRST_COMPOSITION_START_TIME_ANDROID, map, supportedValues);
	frameTimes->lastCompositionStart		=	getTimestamp(EGL_LAST_COMPOSITION_START_TIME_ANDROID, map, supportedValues);
	frameTimes->firstCompositionGpuFinished	=	getTimestamp(EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID, map, supportedValues);
	frameTimes->displayPresent				=	getTimestamp(EGL_DISPLAY_PRESENT_TIME_ANDROID, map, supportedValues);
	frameTimes->dequeueReady				=	getTimestamp(EGL_DEQUEUE_READY_TIME_ANDROID, map, supportedValues);
	frameTimes->readsDone					=	getTimestamp(EGL_READS_DONE_TIME_ANDROID, map, supportedValues);
}

bool timestampValid (EGLnsecsANDROID timestamp)
{
	return (timestamp >= 0) || (timestamp == EGL_TIMESTAMP_PENDING_ANDROID);
}

bool timestampPending (EGLnsecsANDROID timestamp)
{
	return timestamp == EGL_TIMESTAMP_PENDING_ANDROID;
}

void verifySingleFrame (const FrameTimes& frameTimes, tcu::ResultCollector& result, bool verifyReadsDone)
{
	// Verify CPU timeline is monotonic.
	result.check(frameTimes.swapBufferBeginNs < frameTimes.latch, "Buffer latched before it was swapped.");
	result.check(frameTimes.latch < frameTimes.firstCompositionStart, "Buffer composited before it was latched.");
	result.check(frameTimes.firstCompositionStart <= frameTimes.lastCompositionStart, "First composition start after last composition start.");
	result.check(frameTimes.lastCompositionStart < frameTimes.dequeueReady, "Buffer composited after it was ready to be dequeued.");

	// Verify GPU timeline is monotonic.
	if (timestampValid(frameTimes.firstCompositionGpuFinished))
		result.check(frameTimes.renderingComplete < frameTimes.firstCompositionGpuFinished, "Buffer rendering completed after compositor GPU work finished.");

	if (timestampValid(frameTimes.displayPresent))
		result.check(frameTimes.renderingComplete < frameTimes.displayPresent, "Buffer displayed before rendering completed.");

	if (timestampValid(frameTimes.firstCompositionGpuFinished) && timestampValid(frameTimes.displayPresent))
		result.check(frameTimes.firstCompositionGpuFinished < frameTimes.displayPresent, "Buffer displayed before compositor GPU work completed");

	// Drivers may maintain shadow copies of the buffer, so the readsDone time
	// of the real buffer may be earlier than apparent dependencies. We can only
	// be sure that the readsDone time must be after the renderingComplete time.
	if (verifyReadsDone)
		result.check(frameTimes.renderingComplete < frameTimes.readsDone, "Buffer rendering completed after reads completed.");

	// Verify CPU/GPU dependencies
	result.check(frameTimes.renderingComplete < frameTimes.latch, "Buffer latched before rendering completed.");
	if (timestampValid(frameTimes.firstCompositionGpuFinished))
		result.check(frameTimes.firstCompositionStart < frameTimes.firstCompositionGpuFinished, "Composition CPU work started after GPU work finished.");

	if (timestampValid(frameTimes.displayPresent))
		result.check(frameTimes.firstCompositionStart < frameTimes.displayPresent, "Buffer displayed before it was composited.");
}

void verifyNeighboringFrames (const FrameTimes& frame1, const FrameTimes& frame2, tcu::ResultCollector& result, bool verifyReadsDone)
{
	// CPU timeline.
	result.check(frame1.swapBufferBeginNs < frame2.swapBufferBeginNs, "Swap begin times not monotonic.");
	result.check(frame1.latch < frame2.latch, "Latch times not monotonic.");
	result.check(frame1.lastCompositionStart < frame2.latch, "Old buffer composited after new buffer latched.");
	result.check(frame1.lastCompositionStart < frame2.firstCompositionStart, "Composition times overlap.");
	result.check(frame1.dequeueReady < frame2.dequeueReady, "Dequeue ready times not monotonic.");

	// GPU timeline.
	result.check(frame1.renderingComplete < frame2.renderingComplete, "Rendering complete times not monotonic.");

	if (timestampValid(frame1.firstCompositionGpuFinished) && timestampValid(frame2.firstCompositionGpuFinished))
		result.check(frame1.firstCompositionGpuFinished < frame2.firstCompositionGpuFinished, "Composition GPU work complete times not monotonic.");

	if (timestampValid(frame1.displayPresent) && timestampValid(frame2.displayPresent))
		result.check(frame1.displayPresent < frame2.displayPresent, "Display present times not monotonic.");

	if (verifyReadsDone && timestampValid(frame1.readsDone) && timestampValid(frame2.readsDone))
		result.check(frame1.readsDone < frame2.readsDone, "Reads done times not monotonic.");
}

EGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config)
{
	EGLContext		context = EGL_NO_CONTEXT;
	const EGLint	attribList[] =
	{
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};

	EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));

	context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList);
	EGLU_CHECK_MSG(egl, "eglCreateContext() failed");
	TCU_CHECK(context);

	return context;
}

class GetFrameTimestampTest : public SimpleConfigCase
{
public:
							GetFrameTimestampTest	(EglTestContext& eglTestCtx, const NamedFilterList& filters);
							~GetFrameTimestampTest	(void);

private:
	void					executeForConfig		(EGLDisplay display, EGLConfig config);
	void					initializeExtension		(const Library& egl);

	// Not allowed
							GetFrameTimestampTest	(const GetFrameTimestampTest&);
	GetFrameTimestampTest&	operator=				(const GetFrameTimestampTest&);

	// TODO: Move these to eglw::Library.
	eglGetNextFrameIdANDROIDFunc				m_eglGetNextFrameIdANDROID;
	eglGetCompositorTimingANDROIDFunc			m_eglGetCompositorTimingANDROID;
	eglGetCompositorTimingSupportedANDROIDFunc	m_eglGetCompositorTimingSupportedANDROID;
	eglGetFrameTimestampsANDROIDFunc			m_eglGetFrameTimestampsANDROID;
	eglGetFrameTimestampSupportedANDROIDFunc	m_eglGetFrameTimestampSupportedANDROID;

	tcu::ResultCollector						m_result;
};

GetFrameTimestampTest::GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters)
	: SimpleConfigCase							(eglTestCtx, filters.getName(), filters.getDescription(), filters)
	, m_eglGetNextFrameIdANDROID				(DE_NULL)
	, m_eglGetCompositorTimingANDROID			(DE_NULL)
	, m_eglGetCompositorTimingSupportedANDROID	(DE_NULL)
	, m_eglGetFrameTimestampsANDROID			(DE_NULL)
	, m_eglGetFrameTimestampSupportedANDROID	(DE_NULL)
	, m_result									(m_testCtx.getLog())
{
}

GetFrameTimestampTest::~GetFrameTimestampTest (void)
{
}

void GetFrameTimestampTest::initializeExtension (const Library& egl)
{
	m_eglGetNextFrameIdANDROID = reinterpret_cast<eglGetNextFrameIdANDROIDFunc>(egl.getProcAddress("eglGetNextFrameIdANDROID"));
	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetNextFrameIdANDROID failed.");
	m_eglGetCompositorTimingANDROID = reinterpret_cast<eglGetCompositorTimingANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingANDROID"));
	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingANDROID failed.");
	m_eglGetCompositorTimingSupportedANDROID = reinterpret_cast<eglGetCompositorTimingSupportedANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingSupportedANDROID"));
	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingSupportedANDROID failed.");
	m_eglGetFrameTimestampsANDROID = reinterpret_cast<eglGetFrameTimestampsANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampsANDROID"));
	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampsANDROID failed.");
	m_eglGetFrameTimestampSupportedANDROID = reinterpret_cast<eglGetFrameTimestampSupportedANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampSupportedANDROID"));
	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampSupportedANDROID failed.");
}


string getConfigIdString (const Library& egl, EGLDisplay display, EGLConfig config)
{
	std::ostringstream	stream;
	EGLint				id;

	EGLU_CHECK_CALL(egl, getConfigAttrib(display, config , EGL_CONFIG_ID, &id));

	stream << id;

	return stream.str();
}

deUint32 createGLES2Program (const glw::Functions& gl, TestLog& log)
{
	const char* const vertexShaderSource =
	"attribute highp vec2 a_pos;\n"
	"void main (void)\n"
	"{\n"
	"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
	"}";

	const char* const fragmentShaderSource =
	"void main (void)\n"
	"{\n"
	"\tgl_FragColor = vec4(0.9, 0.1, 0.4, 1.0);\n"
	"}";

	deUint32	program			= 0;
	deUint32	vertexShader	= 0;
	deUint32	fragmentShader	= 0;

	deInt32		vertexCompileStatus;
	string		vertexInfoLog;
	deInt32		fragmentCompileStatus;
	string		fragmentInfoLog;
	deInt32		linkStatus;
	string		programInfoLog;

	try
	{
		program			= gl.createProgram();
		vertexShader	= gl.createShader(GL_VERTEX_SHADER);
		fragmentShader	= gl.createShader(GL_FRAGMENT_SHADER);

		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");

		gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
		gl.compileShader(vertexShader);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");

		gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
		gl.compileShader(fragmentShader);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");

		{
			deInt32		infoLogLength = 0;

			gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
			gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);

			vertexInfoLog.resize(infoLogLength, '\0');

			gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0]));
			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");

			vertexInfoLog.resize(infoLogLength);
		}

		{
			deInt32		infoLogLength = 0;

			gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
			gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);

			fragmentInfoLog.resize(infoLogLength, '\0');

			gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0]));
			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");

			fragmentInfoLog.resize(infoLogLength);
		}

		gl.attachShader(program, vertexShader);
		gl.attachShader(program, fragmentShader);
		gl.linkProgram(program);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");

		{
			deInt32		infoLogLength = 0;

			gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
			gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);

			programInfoLog.resize(infoLogLength, '\0');

			gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");

			programInfoLog.resize(infoLogLength);
		}

		if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
		{

			log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());

			log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
			log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog);

			log.endShaderProgram();
		}

		gl.deleteShader(vertexShader);
		gl.deleteShader(fragmentShader);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");

		TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
	}
	catch (...)
	{
		if (program)
			gl.deleteProgram(program);

		if (vertexShader)
			gl.deleteShader(vertexShader);

		if (fragmentShader)
			gl.deleteShader(fragmentShader);

		throw;
	}

	return program;
}

void GetFrameTimestampTest::executeForConfig (EGLDisplay display, EGLConfig config)
{
	const Library&						egl			= m_eglTestCtx.getLibrary();

	if (!eglu::hasExtension(egl, display, "EGL_ANDROID_get_frame_timestamps"))
		TCU_THROW(NotSupportedError, "EGL_ANDROID_get_frame_timestamps is not supported");

	initializeExtension(egl);

	const string						configIdStr	(getConfigIdString(egl, display, config));
	tcu::ScopedLogSection				logSection	(m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str());
	const eglu::NativeWindowFactory&	factory		= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());

	{
		TestLog& log = m_testCtx.getLog();

		log << TestLog::Message << "EGL_RED_SIZE: "		<< eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE)		<< TestLog::EndMessage;
		log << TestLog::Message << "EGL_GREEN_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE)	<< TestLog::EndMessage;
		log << TestLog::Message << "EGL_BLUE_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE)	<< TestLog::EndMessage;
		log << TestLog::Message << "EGL_ALPHA_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE)	<< TestLog::EndMessage;
		log << TestLog::Message << "EGL_DEPTH_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE)	<< TestLog::EndMessage;
		log << TestLog::Message << "EGL_STENCIL_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE)	<< TestLog::EndMessage;
		log << TestLog::Message << "EGL_SAMPLES: "		<< eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES)		<< TestLog::EndMessage;
	}

	de::UniquePtr<eglu::NativeWindow>	window	(factory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(128, 128, eglu::WindowParams::VISIBILITY_VISIBLE)));

	eglu::UniqueSurface					surface	(egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
	eglu::UniqueContext					context	(egl, display, createGLES2Context(egl, display, config));
	glw::Functions						gl;
	deUint32							program = 0;

	EGLU_CHECK_CALL(egl, surfaceAttrib(display, *surface, EGL_TIMESTAMPS_ANDROID, EGL_TRUE));

	m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));

	EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, *context));

	try
	{
		// EGL_DISPLAY_PRESENT_TIME_ANDROID support is currently optional
		// but should be required once HWC1 is no longer supported.
		// All HWC2 devices should support EGL_DISPLAY_PRESENT_TIME_ANDROID.
		TimestampInfoMap timestamps;
		timestamps[EGL_REQUESTED_PRESENT_TIME_ANDROID]				=	TimestampInfo(true,		false, 0);
		timestamps[EGL_RENDERING_COMPLETE_TIME_ANDROID]				=	TimestampInfo(true,		false, 0);
		timestamps[EGL_COMPOSITION_LATCH_TIME_ANDROID]				=	TimestampInfo(true,		false, 0);
		timestamps[EGL_FIRST_COMPOSITION_START_TIME_ANDROID]		=	TimestampInfo(true,		false, 0);
		timestamps[EGL_LAST_COMPOSITION_START_TIME_ANDROID]			=	TimestampInfo(true,		false, 0);
		timestamps[EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID]	=	TimestampInfo(true,		false, 0);
		timestamps[EGL_DISPLAY_PRESENT_TIME_ANDROID]				=	TimestampInfo(false,	false, 0);
		timestamps[EGL_DEQUEUE_READY_TIME_ANDROID]					=	TimestampInfo(true,		false, 0);
		timestamps[EGL_READS_DONE_TIME_ANDROID]						=	TimestampInfo(true,		false, 0);

		const eglw::EGLint invalidTimestampName = EGL_READS_DONE_TIME_ANDROID + 1;

		// Verify required timestamps are supported and populate supportedNames.
		std::vector<eglw::EGLint> supportedNames;
		for (TimestampInfoMap::iterator i = timestamps.begin(); i != timestamps.end(); i++)
		{
			TimestampInfo& info = i->second;
			info.supported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, i->first) != EGL_FALSE;
			EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");

			if (info.supported)
			{
				info.supportedIndex = supportedNames.size();
				supportedNames.push_back(i->first);
			}
			else
				TCU_CHECK_MSG(!info.required, "Required timestamp not supported.");
		}

		// Verify unsupported timestamps are reported properly.
		const bool invalidSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, invalidTimestampName) != EGL_FALSE;
		EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
		TCU_CHECK_MSG(!invalidSupported, "Non existant timestamp reports that it is supported.");

		// Verify compositor timings are supported.
		const bool deadlineSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_DEADLINE_ANDROID) != EGL_FALSE;
		EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
		TCU_CHECK_MSG(deadlineSupported, "EGL_COMPOSITE_DEADLINE_ANDROID not supported.");
		const bool intervalSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_INTERVAL_ANDROID) != EGL_FALSE;
		EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
		TCU_CHECK_MSG(intervalSupported, "EGL_COMPOSITE_INTERVAL_ANDROID not supported.");
		const bool latencySupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID) != EGL_FALSE;
		EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
		TCU_CHECK_MSG(latencySupported, "EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID not supported.");

		const float positions1[] =
		{
			 0.00f,  0.00f,
			 0.75f,  0.00f,
			 0.75f,  0.75f,

			 0.75f,  0.75f,
			 0.00f,  0.75f,
			 0.00f,  0.00f
		};

		const float positions2[] =
		{
			-0.75f, -0.75f,
			 0.00f, -0.75f,
			 0.00f,  0.00f,

			 0.00f,  0.00f,
			-0.75f,  0.00f,
			-0.75f, -0.75f
		};

		deUint32 posLocation;

		program	= createGLES2Program(gl, m_testCtx.getLog());

		gl.useProgram(program);
		posLocation	= gl.getAttribLocation(program, "a_pos");
		gl.enableVertexAttribArray(posLocation);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");

		const size_t frameCount = 120;
		std::vector<FrameTimes> frameTimes(frameCount);
		for (size_t i = 0; i < frameCount; i++)
		{
			FrameTimes& frame = frameTimes[i];

			const eglw::EGLint compositorTimingNames[] =
			{
				EGL_COMPOSITE_DEADLINE_ANDROID,
				EGL_COMPOSITE_INTERVAL_ANDROID,
				EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID,
			};
			const EGLint compositorTimingCount = DE_LENGTH_OF_ARRAY(compositorTimingNames);
			EGLnsecsANDROID compositorTimingValues[compositorTimingCount] = { -2 };

			// Get the current time before making any API calls in case "now"
			// just happens to get sampled near one of the composite deadlines.
			EGLnsecsANDROID now = getNanoseconds();

			// Get the frame id.
			EGLuint64KHR nextFrameId = 0;
			CHECK_NAKED_EGL_CALL(egl, m_eglGetNextFrameIdANDROID(display, *surface, &nextFrameId));
			frame.frameId				=	nextFrameId;

			// Get the compositor timing.
			CHECK_NAKED_EGL_CALL(egl, m_eglGetCompositorTimingANDROID(
				display, *surface, compositorTimingCount,
				compositorTimingNames, compositorTimingValues));
			frame.compositeDeadline			=	compositorTimingValues[0];
			frame.compositeInterval			=	compositorTimingValues[1];
			frame.compositeToPresentLatency	=	compositorTimingValues[2];

			// Verify compositor timing is sane.
			m_result.check(1000000 < frame.compositeInterval, "Reported refresh rate greater than 1kHz.");
			m_result.check(frame.compositeInterval < 1000000000, "Reported refresh rate less than 1Hz.");
			m_result.check(0 < frame.compositeToPresentLatency, "Composite to present latency must be greater than 0.");
			m_result.check(frame.compositeToPresentLatency < frame.compositeInterval * 3, "Composite to present latency is more than 3 vsyncs.");
			const EGLnsecsANDROID minDeadline = now;
			m_result.check(minDeadline < frame.compositeDeadline, "Next composite deadline is in the past.");
			const EGLnsecsANDROID maxDeadline = now + frame.compositeInterval * 2;
			m_result.check(frame.compositeDeadline < maxDeadline, "Next composite deadline over two intervals away.");

			const float colorAngle = (static_cast<float>(i) / static_cast<float>(frameCount)) * 6.28318f;
			gl.clearColor((1.0f + deFloatSin(colorAngle)) / 2.0f, 0.7f, (1.0f + deFloatCos(colorAngle)) / 2.0f, 1.0f);
			gl.clear(GL_COLOR_BUFFER_BIT);
			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");

			const bool posSelect  = ((i % 2) == 0);
			gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, posSelect ? positions1 : positions2);
			gl.drawArrays(GL_TRIANGLES, 0, 6);
			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");

			frame.swapBufferBeginNs = getNanoseconds();
			EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));

			// All timestamps from 5 frames ago should definitely be available.
			const size_t frameDelay = 5;
			if (i >= frameDelay)
			{
				// \todo [2017-01-25 brianderson] Remove this work around once reads done is fixed.
				const bool verifyReadsDone	=	i > (frameDelay + 3);
				FrameTimes&		frame5ago	=	frameTimes[i-frameDelay];
				std::vector<EGLnsecsANDROID> supportedValues(supportedNames.size(), 0);

				CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
					display, *surface, frame5ago.frameId, static_cast<eglw::EGLint>(supportedNames.size()),
					&supportedNames[0], &supportedValues[0]));
				populateFrameTimes(&frame5ago, timestamps, supportedValues);

				verifySingleFrame(frame5ago, m_result, verifyReadsDone);
				if (i >= frameDelay + 1)
				{
					FrameTimes& frame6ago = frameTimes[i-frameDelay-1];
					verifyNeighboringFrames(frame6ago, frame5ago, m_result, verifyReadsDone);
				}
			}
		}

		// All timestamps for the most recently swapped frame should
		// become available by only polling eglGetFrametimestamps.
		// No additional swaps should be necessary.
		FrameTimes&				lastFrame				=	frameTimes.back();
		const EGLnsecsANDROID	pollingDeadline			=	lastFrame.swapBufferBeginNs + 1000000000;
		bool					finalTimestampAvailable	=	false;

		do
		{
			std::vector<EGLnsecsANDROID> supportedValues(supportedNames.size(), 0);
			CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
				display, *surface, lastFrame.frameId, static_cast<eglw::EGLint>(supportedNames.size()),
				&supportedNames[0], &supportedValues[0]));
			populateFrameTimes(&lastFrame, timestamps, supportedValues);

			// Poll for present if it's supported.
			// Otherwise, poll for firstCompositionStart.
			if (timestamps[EGL_DISPLAY_PRESENT_TIME_ANDROID].supported)
				finalTimestampAvailable = !timestampPending(lastFrame.displayPresent);
			else
				finalTimestampAvailable = !timestampPending(lastFrame.firstCompositionStart);
		} while (!finalTimestampAvailable && (getNanoseconds() < pollingDeadline));

		m_result.check(finalTimestampAvailable, "Timed out polling for timestamps of last swap.");
		m_result.check((lastFrame.requestedPresent >= 0), "Requested present of last swap not avaiable.");
		m_result.check((lastFrame.renderingComplete >= 0), "Rendering complete of last swap not avaiable.");
		m_result.check((lastFrame.latch >= 0), "Latch of last swap not avaiable.");
		m_result.check((lastFrame.firstCompositionStart >= 0), "First composite time of last swap not avaiable.");
		m_result.check((lastFrame.lastCompositionStart >= 0), "Last composite time of last swap not avaiable.");

		window->processEvents();
		gl.disableVertexAttribArray(posLocation);
		gl.useProgram(0);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to release program state");

		gl.deleteProgram(program);
		program = 0;
		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()");

		m_result.setTestContextResult(m_testCtx);
	}
	catch (...)
	{
		if (program != 0)
			gl.deleteProgram(program);

		EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
		throw;
	}

	EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
}

class GetFrameTimestampsTests : public TestCaseGroup
{
public:
								GetFrameTimestampsTests	(EglTestContext& eglTestCtx);
	void						init					(void);

private:
								GetFrameTimestampsTests	(const GetFrameTimestampsTests&);
	GetFrameTimestampsTests&	operator=				(const GetFrameTimestampsTests&);
};


GetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx)
	: TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests")
{
}

bool isWindow (const eglu::CandidateConfig& c)
{
	return (c.surfaceType() & EGL_WINDOW_BIT) != 0;
}

void GetFrameTimestampsTests::init (void)
{
	eglu::FilterList baseFilters;
	baseFilters << isWindow;

	vector<NamedFilterList> filterLists;
	getDefaultFilterLists(filterLists, baseFilters);

	for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
		addChild(new GetFrameTimestampTest(m_eglTestCtx, *i));
}

} // anonymous

TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx)
{
	return new GetFrameTimestampsTests(eglTestCtx);
}

} // egl
} // deqp
