/*-------------------------------------------------------------------------
 * drawElements Quality Program EGL Module
 * ---------------------------------------
 *
 * Copyright 2015 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 EXT_buffer_age
 *//*--------------------------------------------------------------------*/

#include "teglBufferAgeTests.hpp"

#include "tcuImageCompare.hpp"
#include "tcuTestLog.hpp"
#include "tcuSurface.hpp"
#include "tcuTextureUtil.hpp"

#include "egluNativeWindow.hpp"
#include "egluUtil.hpp"
#include "egluConfigFilter.hpp"

#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"

#include "gluDefs.hpp"
#include "gluRenderContext.hpp"
#include "gluShaderProgram.hpp"

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

#include "deRandom.hpp"
#include "deString.h"

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

using std::string;
using std::vector;
using glw::GLubyte;
using tcu::IVec2;

using namespace eglw;

namespace deqp
{
namespace egl
{
namespace
{

typedef	tcu::Vector<GLubyte, 3> Color;

class GLES2Renderer;

class ReferenceRenderer;

class BufferAgeTest : public TestCase
{
public:
	enum DrawType
	{
		DRAWTYPE_GLES2_CLEAR,
		DRAWTYPE_GLES2_RENDER
	};

								BufferAgeTest	(EglTestContext& eglTestCtx, bool preserveColorBuffer, const vector<DrawType>& oddFrameDrawType,
												 const vector<DrawType>& evenFrameDrawType, const char* name, const char* description);
								~BufferAgeTest	(void);

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

private:
	void						initEGLSurface (EGLConfig config);
	void						initEGLContext (EGLConfig config);

	const int					m_seed;
	const bool					m_preserveColorBuffer;
	const vector<DrawType>		m_oddFrameDrawType;
	const vector<DrawType>		m_evenFrameDrawType;

	EGLDisplay					m_eglDisplay;
	eglu::NativeWindow*			m_window;
	EGLSurface					m_eglSurface;
	EGLConfig					m_eglConfig;
	EGLContext					m_eglContext;
	glw::Functions				m_gl;

	GLES2Renderer*				m_gles2Renderer;
	ReferenceRenderer*			m_refRenderer;

};

struct ColoredRect
{
public:
							ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_);
	IVec2	 				bottomLeft;
	IVec2 					topRight;
	Color 					color;
};

ColoredRect::ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_)
	: bottomLeft(bottomLeft_)
	, topRight	(topRight_)
	, color		(color_)
{
}

struct DrawCommand
{
							DrawCommand (const BufferAgeTest::DrawType drawType_, const ColoredRect& rect_);
	BufferAgeTest::DrawType drawType;
	ColoredRect				rect;
};

DrawCommand::DrawCommand (const BufferAgeTest::DrawType drawType_, const ColoredRect& rect_)
	: drawType(drawType_)
	, rect    (rect_)
{
}

struct Frame
{
						Frame (int width_, int height_);
	int 				width;
	int					height;
	vector<DrawCommand> draws;
};

Frame::Frame (int width_, int height_)
	: width(width_)
	, height(height_)
{
}


// (x1,y1) lie in the lower-left quadrant while (x2,y2) lie in the upper-right.
// the coords are multiplied by 4 to amplify the minimial difference between coords to 4 (if not zero)
// to avoid the situation where two edges are too close to each other which makes the rounding error
// intoleratable by compareToReference()
void generateRandomFrame (Frame* dst, const vector<BufferAgeTest::DrawType>& drawTypes, de::Random& rnd)
{
	for (size_t ndx = 0; ndx < drawTypes.size(); ndx++)
	{
		const int			x1			= rnd.getInt(0, (dst->width-1)/8) * 4;
		const int			y1			= rnd.getInt(0, (dst->height-1)/8) * 4;
		const int			x2			= rnd.getInt((dst->width-1)/8, (dst->width-1)/4) * 4;
		const int			y2			= rnd.getInt((dst->height-1)/8, (dst->height-1)/4) * 4;
		const GLubyte		r			= rnd.getUint8();
		const GLubyte		g			= rnd.getUint8();
		const GLubyte		b			= rnd.getUint8();
		const ColoredRect	coloredRect	(IVec2(x1, y1), IVec2(x2, y2), Color(r, g, b));
		const DrawCommand	drawCommand (drawTypes[ndx], coloredRect);
		(*dst).draws.push_back(drawCommand);
	}
}

typedef vector<Frame> FrameSequence;

//helper function declaration
EGLConfig		getEGLConfig					(const Library& egl, EGLDisplay eglDisplay, bool preserveColorBuffer);
void			clearColorScreen				(const glw::Functions& gl, const tcu::Vec4& clearColor);
void			clearColorReference				(tcu::Surface* ref, const tcu::Vec4& clearColor);
void			readPixels						(const glw::Functions& gl, tcu::Surface* screen);
float			windowToDeviceCoordinates		(int x, int length);
bool			compareToReference				(tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& buffer, int frameNdx, int bufferNum);
vector<int> 	getFramesOnBuffer 				(const vector<int>& bufferAges, int frameNdx);

class GLES2Renderer
{
public:
							GLES2Renderer		(const glw::Functions& gl);
							~GLES2Renderer		(void);
	void					render				(int width, int height, const Frame& frame) const;

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

	const glw::Functions&	m_gl;
	glu::ShaderProgram		m_glProgram;
	glw::GLuint				m_coordLoc;
	glw::GLuint				m_colorLoc;
};

// generate sources for vertex and fragment buffer
glu::ProgramSources getSources (void)
{
	const char* const vertexShaderSource =
		"attribute mediump vec4 a_pos;\n"
		"attribute mediump vec4 a_color;\n"
		"varying mediump vec4 v_color;\n"
		"void main(void)\n"
		"{\n"
		"\tv_color = a_color;\n"
		"\tgl_Position = a_pos;\n"
		"}";

	const char* const fragmentShaderSource =
		"varying mediump vec4 v_color;\n"
		"void main(void)\n"
		"{\n"
		"\tgl_FragColor = v_color;\n"
		"}";

	return glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource);
}

GLES2Renderer::GLES2Renderer (const glw::Functions& gl)
	: m_gl		  (gl)
	, m_glProgram (gl, getSources())
	, m_coordLoc  ((glw::GLuint)-1)
	, m_colorLoc  ((glw::GLuint)-1)
{
	m_colorLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_color");
	m_coordLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_pos");
	GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to get attribute locations");
}

GLES2Renderer::~GLES2Renderer (void)
{
}

void GLES2Renderer::render (int width, int height, const Frame& frame) const
{
	for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
	{
		const ColoredRect& coloredRect = frame.draws[drawNdx].rect;
		if (frame.draws[drawNdx].drawType == BufferAgeTest::DRAWTYPE_GLES2_RENDER)
		{
			float x1 = windowToDeviceCoordinates(coloredRect.bottomLeft.x(), width);
			float y1 = windowToDeviceCoordinates(coloredRect.bottomLeft.y(), height);
			float x2 = windowToDeviceCoordinates(coloredRect.topRight.x(), width);
			float y2 = windowToDeviceCoordinates(coloredRect.topRight.y(), height);

			const glw::GLfloat coords[] =
			{
				x1, y1, 0.0f, 1.0f,
				x1, y2, 0.0f, 1.0f,
				x2, y2, 0.0f, 1.0f,

				x2, y2, 0.0f, 1.0f,
				x2, y1, 0.0f, 1.0f,
				x1, y1, 0.0f, 1.0f
			};

			const glw::GLubyte colors[] =
			{
				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,

				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
			};

			m_gl.useProgram(m_glProgram.getProgram());
			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");

			m_gl.enableVertexAttribArray(m_coordLoc);
			m_gl.enableVertexAttribArray(m_colorLoc);
			GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to enable attributes");

			m_gl.vertexAttribPointer(m_coordLoc, 4, GL_FLOAT, GL_FALSE, 0, coords);
			m_gl.vertexAttribPointer(m_colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors);
			GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to set attribute pointers");

			m_gl.drawArrays(GL_TRIANGLES, 0, DE_LENGTH_OF_ARRAY(coords)/4);
			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays(), failed");

			m_gl.disableVertexAttribArray(m_coordLoc);
			m_gl.disableVertexAttribArray(m_colorLoc);
			GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to disable attributes");

			m_gl.useProgram(0);
			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
		}
		else if (frame.draws[drawNdx].drawType == BufferAgeTest::DRAWTYPE_GLES2_CLEAR)
		{
			m_gl.enable(GL_SCISSOR_TEST);
			m_gl.scissor(coloredRect.bottomLeft.x(), coloredRect.bottomLeft.y(),
						 coloredRect.topRight.x()-coloredRect.bottomLeft.x(), coloredRect.topRight.y()-coloredRect.bottomLeft.y());
			m_gl.clearColor(coloredRect.color.x()/255.0f, coloredRect.color.y()/255.0f, coloredRect.color.z()/255.0f, 1.0f);
			m_gl.clear(GL_COLOR_BUFFER_BIT);
			m_gl.disable(GL_SCISSOR_TEST);
		}
		else
			DE_ASSERT(false);
	}
}

class ReferenceRenderer
{
public:
						ReferenceRenderer 	(void);
	void				render			  	(tcu::Surface* target, const Frame& frame) const;
private:
						ReferenceRenderer	(const ReferenceRenderer&);
	ReferenceRenderer&	operator=		  	(const ReferenceRenderer&);
};

ReferenceRenderer::ReferenceRenderer(void)
{
}

void ReferenceRenderer::render (tcu::Surface* target, const Frame& frame) const
{
	for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
	{
		const ColoredRect& coloredRect = frame.draws[drawNdx].rect;
		if (frame.draws[drawNdx].drawType == BufferAgeTest::DRAWTYPE_GLES2_RENDER || frame.draws[drawNdx].drawType == BufferAgeTest::DRAWTYPE_GLES2_CLEAR)
		{
			const tcu::UVec4 color(coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255);
			tcu::clear(tcu::getSubregion(target->getAccess(), coloredRect.bottomLeft.x(), coloredRect.bottomLeft.y(),
										 coloredRect.topRight.x()-coloredRect.bottomLeft.x(), coloredRect.topRight.y()-coloredRect.bottomLeft.y()), color);
		}
		else
			DE_ASSERT(false);
	}
}

BufferAgeTest::BufferAgeTest (EglTestContext& eglTestCtx, bool preserveColorBuffer, const vector<DrawType>& oddFrameDrawType, const vector<DrawType>& evenFrameDrawType,
							  const char* name, const char* description)
	: TestCase				(eglTestCtx, name, description)
	, m_seed				(deStringHash(name))
	, m_preserveColorBuffer (preserveColorBuffer)
	, m_oddFrameDrawType	(oddFrameDrawType)
	, m_evenFrameDrawType	(evenFrameDrawType)
	, m_eglDisplay			(EGL_NO_DISPLAY)
	, m_window				(DE_NULL)
	, m_eglSurface			(EGL_NO_SURFACE)
	, m_eglContext			(EGL_NO_CONTEXT)
	, m_gles2Renderer		(DE_NULL)
	, m_refRenderer			(DE_NULL)
{
}

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

void BufferAgeTest::init (void)
{
	const Library&	egl	= m_eglTestCtx.getLibrary();

	m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
	m_eglConfig	 = getEGLConfig(m_eglTestCtx.getLibrary(), m_eglDisplay, m_preserveColorBuffer);

	if (m_eglConfig == DE_NULL)
		TCU_THROW(NotSupportedError, "No supported config found");

	//create surface and context and make them current
	initEGLSurface(m_eglConfig);
	initEGLContext(m_eglConfig);

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

	if (eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_buffer_age") == false)
		TCU_THROW(NotSupportedError, "EGL_EXT_buffer_age is not supported");

	m_gles2Renderer = new GLES2Renderer(m_gl);
	m_refRenderer   = new ReferenceRenderer();
}

void BufferAgeTest::deinit (void)
{
	const Library& egl = m_eglTestCtx.getLibrary();

	delete m_refRenderer;
	m_refRenderer = DE_NULL;

	delete m_gles2Renderer;
	m_gles2Renderer = DE_NULL;

	if (m_eglContext != EGL_NO_CONTEXT)
	{
		egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
		egl.destroyContext(m_eglDisplay, m_eglContext);
		m_eglContext = EGL_NO_CONTEXT;
	}

	if (m_eglSurface != EGL_NO_SURFACE)
	{
		egl.destroySurface(m_eglDisplay, m_eglSurface);
		m_eglSurface = EGL_NO_SURFACE;
	}

	if (m_eglDisplay != EGL_NO_DISPLAY)
	{
		egl.terminate(m_eglDisplay);
		m_eglDisplay = EGL_NO_DISPLAY;
	}

	delete m_window;
	m_window = DE_NULL;
}

void BufferAgeTest::initEGLSurface (EGLConfig config)
{
	const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
	m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, config, DE_NULL,
									eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
	m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, config, DE_NULL);
}

void BufferAgeTest::initEGLContext (EGLConfig config)
{
	const Library& 	egl 		 = m_eglTestCtx.getLibrary();
	const EGLint 	attribList[] =
	{
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};

	egl.bindAPI(EGL_OPENGL_ES_API);
	m_eglContext = egl.createContext(m_eglDisplay, config, EGL_NO_CONTEXT, attribList);
	EGLU_CHECK_MSG(egl, "eglCreateContext");
	DE_ASSERT(m_eglSurface != EGL_NO_SURFACE);
	egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
	EGLU_CHECK_MSG(egl, "eglMakeCurrent");
}

// return indices of frames that have been written to the given buffer
vector<int> getFramesOnBuffer (const vector<int>& bufferAges, int frameNdx)
{
	DE_ASSERT(frameNdx < (int)bufferAges.size());
	vector<int> frameOnBuffer;
	int 		age = bufferAges[frameNdx];
	while (age != 0)
	{
		frameNdx = frameNdx - age;
		DE_ASSERT(frameNdx >= 0);
		frameOnBuffer.push_back(frameNdx);
		age = bufferAges[frameNdx];
	}

	reverse(frameOnBuffer.begin(), frameOnBuffer.end());
	return frameOnBuffer;
}

TestCase::IterateResult BufferAgeTest::iterate (void)
{
	de::Random 		rnd					(m_seed);
	const Library&	egl					= m_eglTestCtx.getLibrary();
	tcu::TestLog& 	log					= m_testCtx.getLog();
	const int 		width				= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
	const int 		height				= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
	const float 	clearRed			= rnd.getFloat();
	const float 	clearGreen			= rnd.getFloat();
	const float 	clearBlue			= rnd.getFloat();
	const tcu::Vec4	clearColor			(clearRed, clearGreen, clearBlue, 1.0f);
	const int 		numFrames			= 20;
	FrameSequence 	frameSequence;
	vector<int> 	bufferAges;

	if (m_preserveColorBuffer)
		EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED));
	else
		EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));

	for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
	{
		tcu::Surface					currentBuffer			(width, height);
		tcu::Surface					refBuffer				(width, height);
		Frame			   				newFrame				(width, height);
		EGLint							currentBufferAge		= -1;

		if (frameNdx % 2 == 0)
			generateRandomFrame(&newFrame, m_evenFrameDrawType, rnd);
		else
			generateRandomFrame(&newFrame, m_oddFrameDrawType, rnd);

		frameSequence.push_back(newFrame);

		EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_EXT, &currentBufferAge));

		if (currentBufferAge > frameNdx || currentBufferAge < 0) // invalid buffer age
		{
			std::ostringstream stream;
			stream << "Fail, the age is invalid. Age: " << currentBufferAge << ", frameNdx: " << frameNdx;
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, stream.str().c_str());
			return STOP;
		}

		if (frameNdx > 0 && m_preserveColorBuffer && currentBufferAge != 1)
		{
			std::ostringstream stream;
			stream << "Fail, EGL_BUFFER_PRESERVED is set to true, but buffer age is: " << currentBufferAge << " (should be 1)";
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, stream.str().c_str());
			return STOP;
		}

		bufferAges.push_back(currentBufferAge);
		DE_ASSERT((int)bufferAges.size() == frameNdx+1);

		// during first half, just keep rendering without reading pixel back to mimic ordinary use case
		if (frameNdx < numFrames/2)
		{
			if (currentBufferAge == 0)
				clearColorScreen(m_gl, clearColor);

			m_gles2Renderer->render(width, height, newFrame);
			EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
			continue;
		}

		// do verification in the second half
		if (currentBufferAge > 0) //buffer contain previous content, need to verify
		{
			const vector<int> framesOnBuffer = getFramesOnBuffer(bufferAges, frameNdx);
			readPixels(m_gl, &currentBuffer);
			clearColorReference(&refBuffer, clearColor);

			for (vector<int>::const_iterator it = framesOnBuffer.begin(); it != framesOnBuffer.end(); it++)
				m_refRenderer->render(&refBuffer, frameSequence[*it]);

			if (compareToReference(log, refBuffer, currentBuffer, frameNdx, frameNdx-currentBufferAge) == false)
			{
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, buffer content is not well preserved when age > 0");
				return STOP;
			}
		}
		else // currentBufferAge == 0, content is undefined, clear the buffer, currentBufferAge < 0 is ruled out at the beginning
		{
			clearColorScreen(m_gl, clearColor);
			clearColorReference(&refBuffer, clearColor);
		}

		m_gles2Renderer->render(width, height, newFrame);
		m_refRenderer->render(&refBuffer, newFrame);

		readPixels(m_gl, &currentBuffer);

		if (compareToReference(log, refBuffer, currentBuffer, frameNdx, frameNdx) == false)
		{
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail, render result is wrong");
			return STOP;
		}

		EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
	}

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	return STOP;
}

string generateDrawTypeName (const vector<BufferAgeTest::DrawType>& drawTypes)
{
	std::ostringstream stream;
	if (drawTypes.size() == 0)
		return string("_none");

	for (size_t ndx = 0; ndx < drawTypes.size(); ndx++)
	{
		if (drawTypes[ndx] == BufferAgeTest::DRAWTYPE_GLES2_RENDER)
			stream << "_render";
		else if (drawTypes[ndx] == BufferAgeTest::DRAWTYPE_GLES2_CLEAR)
			stream << "_clear";
		else
			DE_ASSERT(false);
	}
	return stream.str();
}

string generateTestName (const vector<BufferAgeTest::DrawType>& oddFrameDrawType, const vector<BufferAgeTest::DrawType>& evenFrameDrawType)
{
	return "odd" + generateDrawTypeName(oddFrameDrawType) + "_even" + generateDrawTypeName(evenFrameDrawType);
}

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

bool isES2Renderable (const eglu::CandidateConfig& c)
{
	return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
}

bool hasPreserveSwap (const eglu::CandidateConfig& c)
{
	return (c.surfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
}

EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveColorBuffer)
{
	eglu::FilterList filters;
 	filters << isWindow << isES2Renderable;
 	if (preserveColorBuffer)
 		filters << hasPreserveSwap;
 	return eglu::chooseSingleConfig(egl, eglDisplay, filters);
}

void clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor)
{
	gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
	gl.clear(GL_COLOR_BUFFER_BIT);
}

void clearColorReference (tcu::Surface* ref, const tcu::Vec4& clearColor)
{
	tcu::clear(ref->getAccess(), clearColor);
}

void readPixels (const glw::Functions& gl, tcu::Surface* screen)
{
	gl.readPixels(0, 0, screen->getWidth(), screen->getHeight(),  GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr());
}

float windowToDeviceCoordinates (int x, int length)
{
	return (2.0f * float(x) / float(length)) - 1.0f;
}

bool compareToReference (tcu::TestLog& log,	 const tcu::Surface& reference, const tcu::Surface& buffer, int frameNdx, int bufferNum)
{
	std::ostringstream stream;
	stream << "FrameNdx = " << frameNdx << ", compare current buffer (numbered: " << bufferNum << ") to reference";
	return tcu::intThresholdPositionDeviationCompare(log, "buffer age test", stream.str().c_str(), reference.getAccess(), buffer.getAccess(),
													 tcu::UVec4(8, 8, 8, 0), tcu::IVec3(2,2,0), true, tcu::COMPARE_LOG_RESULT);
}

} // anonymous

BufferAgeTests::BufferAgeTests (EglTestContext& eglTestCtx)
	: TestCaseGroup(eglTestCtx, "buffer_age", "Color buffer age tests")
{
}

void BufferAgeTests::init (void)
{
	const BufferAgeTest::DrawType clearRender[2] =
	{
		BufferAgeTest::DRAWTYPE_GLES2_CLEAR,
		BufferAgeTest::DRAWTYPE_GLES2_RENDER
	};

	const BufferAgeTest::DrawType renderClear[2] =
	{
		BufferAgeTest::DRAWTYPE_GLES2_RENDER,
		BufferAgeTest::DRAWTYPE_GLES2_CLEAR
	};

	vector< vector<BufferAgeTest::DrawType> > frameDrawTypes;
	frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> ());
	frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (1, BufferAgeTest::DRAWTYPE_GLES2_CLEAR));
	frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (1, BufferAgeTest::DRAWTYPE_GLES2_RENDER));
	frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (2, BufferAgeTest::DRAWTYPE_GLES2_CLEAR));
	frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (2, BufferAgeTest::DRAWTYPE_GLES2_RENDER));
	frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (DE_ARRAY_BEGIN(clearRender), DE_ARRAY_END(clearRender)));
	frameDrawTypes.push_back(vector<BufferAgeTest::DrawType> (DE_ARRAY_BEGIN(renderClear), DE_ARRAY_END(renderClear)));

	for (int preserveNdx = 0; preserveNdx < 2; preserveNdx++)
	{
		const bool			 preserve 		= (preserveNdx == 0);
		TestCaseGroup* const preserveGroup 	= new TestCaseGroup(m_eglTestCtx, (preserve ? "preserve" : "no_preserve"), "");

		for (size_t evenNdx = 0; evenNdx < frameDrawTypes.size(); evenNdx++)
		{
			const vector<BufferAgeTest::DrawType>& evenFrameDrawType = frameDrawTypes[evenNdx];

			for (size_t oddNdx = evenNdx; oddNdx < frameDrawTypes.size(); oddNdx++)
			{
				const vector<BufferAgeTest::DrawType>& 	oddFrameDrawType = frameDrawTypes[oddNdx];
				const std::string 						name 			 = generateTestName(oddFrameDrawType, evenFrameDrawType);
				preserveGroup->addChild(new BufferAgeTest(m_eglTestCtx, preserve, oddFrameDrawType, evenFrameDrawType, name.c_str(), ""));
			}
		}
		addChild(preserveGroup);
	}
}

} // egl
} // deqp
