/*-------------------------------------------------------------------------
 * 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 KHR_swap_buffer_with_damage
 *//*--------------------------------------------------------------------*/

#include "teglSwapBuffersWithDamageTests.hpp"

#include "tcuImageCompare.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;

enum DrawType
{
    DRAWTYPE_GLES2_CLEAR,
    DRAWTYPE_GLES2_RENDER
};

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 (DrawType drawType_, const ColoredRect& rect_);
    DrawType	drawType;
	ColoredRect	rect;
};

DrawCommand::DrawCommand (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_)
{
}

typedef vector<Frame> FrameSequence;

//helper function declaration
EGLConfig		getEGLConfig					(const Library& egl, EGLDisplay eglDisplay, bool preserveBuffer);
void			clearColorScreen				(const glw::Functions& gl, const tcu::Vec4& clearColor);
float			windowToDeviceCoordinates		(int x, int length);

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 vec2 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 = vec4(a_pos, 0.0, 1.0);\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 == DRAWTYPE_GLES2_RENDER)
		{
			const float x1 = windowToDeviceCoordinates(coloredRect.bottomLeft.x(), width);
			const float y1 = windowToDeviceCoordinates(coloredRect.bottomLeft.y(), height);
			const float x2 = windowToDeviceCoordinates(coloredRect.topRight.x(), width);
			const float y2 = windowToDeviceCoordinates(coloredRect.topRight.y(), height);

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

				x2, y2,
				x2, y1,
				x1, y1,
			};

			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, 2, 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)/2);
			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 == 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_FATAL("Invalid drawtype");
	}
}

class SwapBuffersWithDamageTest : public TestCase
{
public:
								SwapBuffersWithDamageTest		(EglTestContext& eglTestCtx,
																 const vector<DrawType>& frameDrawType,
																 int iterationTimes,
																 const char* name,
																 const char* description);
								~SwapBuffersWithDamageTest		(void);

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

protected:
	virtual EGLConfig			getConfig						(const Library& egl, EGLDisplay eglDisplay);
	virtual void				checkExtension					(const Library& egl, EGLDisplay eglDisplay);
	void						initEGLSurface					(EGLConfig config);
	void						initEGLContext					(EGLConfig config);

	eglu::NativeWindow*			m_window;
	EGLConfig					m_eglConfig;
	EGLContext					m_eglContext;
	const int					m_seed;
	const int					m_iterationTimes;
	const vector<DrawType>	    m_frameDrawType;
	EGLDisplay					m_eglDisplay;
	EGLSurface					m_eglSurface;
	glw::Functions				m_gl;
	GLES2Renderer*				m_gles2Renderer;
};

SwapBuffersWithDamageTest::SwapBuffersWithDamageTest (EglTestContext& eglTestCtx, const vector<DrawType>& frameDrawType, int iterationTimes,  const char* name, const char* description)
	: TestCase		  (eglTestCtx, name, description)
	, m_window		  (DE_NULL)
	, m_eglContext	  (EGL_NO_CONTEXT)
	, m_seed		  (deStringHash(name))
	, m_iterationTimes(iterationTimes)
	, m_frameDrawType (frameDrawType)
	, m_eglDisplay	  (EGL_NO_DISPLAY)
	, m_eglSurface	  (EGL_NO_SURFACE)
	, m_gles2Renderer (DE_NULL)
{
}

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

EGLConfig SwapBuffersWithDamageTest::getConfig (const Library& egl, EGLDisplay eglDisplay)
{
	return getEGLConfig(egl, eglDisplay, false);
}

void SwapBuffersWithDamageTest::checkExtension (const Library& egl, EGLDisplay eglDisplay)
{
	if (!eglu::hasExtension(egl, eglDisplay, "EGL_KHR_swap_buffers_with_damage"))
		TCU_THROW(NotSupportedError, "EGL_KHR_swap_buffers_with_damage is not supported");
}

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

	m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
	m_eglConfig  = getConfig(egl, m_eglDisplay);

	checkExtension(egl, m_eglDisplay);

	initEGLSurface(m_eglConfig);
	initEGLContext(m_eglConfig);

	m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
	m_gles2Renderer = new GLES2Renderer(m_gl);
}

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

	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 SwapBuffersWithDamageTest::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 SwapBuffersWithDamageTest::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");
	TCU_CHECK(m_eglSurface != EGL_NO_SURFACE);
	egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
	EGLU_CHECK_MSG(egl, "eglMakeCurrent");
}

FrameSequence	generateFrameSequence	(const vector<DrawType>& frameDrawType, de::Random& rnd, int numFrames, int width, int height);
vector<EGLint>	getDamageRegion			(const Frame& frame);

TestCase::IterateResult SwapBuffersWithDamageTest::iterate (void)
{
	de::Random			rnd				(m_seed);
	const Library&		egl				= m_eglTestCtx.getLibrary();
	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		= 24; // (width, height) = (480, 480) --> numFrame = 24, divisible
	const FrameSequence frameSequence	= generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height);

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));

	for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++)
	{
		for (int currentFrameNdx = 0; currentFrameNdx < numFrames; currentFrameNdx++)
		{
			vector<EGLint>	damageRegion = getDamageRegion(frameSequence[currentFrameNdx]);

			clearColorScreen(m_gl, clearColor);
			for (int ndx = 0; ndx <= currentFrameNdx; ndx++)
				m_gles2Renderer->render(width, height, frameSequence[ndx]);

			EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
		}
	}
	return STOP;
}

class SwapBuffersWithDamageAndPreserveBufferTest : public SwapBuffersWithDamageTest
{
public:
					SwapBuffersWithDamageAndPreserveBufferTest	(EglTestContext& eglTestCtx,
																 const vector<DrawType>& frameDrawType,
																 int itertionTimes,
																 const char* name,
																 const char* description);
	IterateResult	iterate										(void);

protected:
	EGLConfig		getConfig									(const Library& egl, EGLDisplay eglDisplay);
};

SwapBuffersWithDamageAndPreserveBufferTest::SwapBuffersWithDamageAndPreserveBufferTest (EglTestContext& eglTestCtx,
																						const vector<DrawType>& frameDrawType,
																						int iterationTimes,
																						const char* name,
																						const char* description)
	: SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, name, description)
{
}

EGLConfig SwapBuffersWithDamageAndPreserveBufferTest::getConfig (const Library& egl, EGLDisplay eglDisplay)
{
	return getEGLConfig(egl, eglDisplay, true);
}

TestCase::IterateResult SwapBuffersWithDamageAndPreserveBufferTest::iterate (void)
{

	de::Random			rnd				(m_seed);
	const Library&		egl				= m_eglTestCtx.getLibrary();
	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		= 24; // (width, height) = (480, 480) --> numFrame = 24, divisible
	const FrameSequence frameSequence	= generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height);

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED));

	for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++)
	{
		clearColorScreen(m_gl, clearColor);
		EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, DE_NULL, 0));

		for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
		{
			const Frame&	currentFrame = frameSequence[frameNdx];
			vector<EGLint>	damageRegion = getDamageRegion(currentFrame);

			m_gles2Renderer->render(width, height, currentFrame);
			EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
		}
	}

	return STOP;
}

class SwapBuffersWithDamageAndBufferAgeTest : public SwapBuffersWithDamageTest
{
public:
					SwapBuffersWithDamageAndBufferAgeTest	(EglTestContext& eglTestCtx,
															 const vector<DrawType>& frameDrawType,
															 int iterationTimes,
															 const char* name,
															 const char* description);
	IterateResult	iterate									(void);

protected:
	void			checkExtension							(const Library& egl, EGLDisplay eglDisplay);
};

SwapBuffersWithDamageAndBufferAgeTest::SwapBuffersWithDamageAndBufferAgeTest (EglTestContext& eglTestCtx,
																			  const vector<DrawType>& frameDrawType,
																			  int iterationTimes,
																			  const char* name,
																			  const char* description)
	: SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, name, description)
{
}


void SwapBuffersWithDamageAndBufferAgeTest::checkExtension (const Library& egl, EGLDisplay eglDisplay)
{
	if (!eglu::hasExtension(egl, eglDisplay, "EGL_KHR_swap_buffers_with_damage"))
		TCU_THROW(NotSupportedError, "EGL_KHR_swap_buffers_with_damage is not supported");

	if (!eglu::hasExtension(egl, eglDisplay, "EGL_EXT_buffer_age"))
		TCU_THROW(NotSupportedError, "EGL_EXT_buffer_age not supported");
}

TestCase::IterateResult SwapBuffersWithDamageAndBufferAgeTest::iterate (void)
{

	de::Random			rnd				(m_seed);
	const Library&		egl				= m_eglTestCtx.getLibrary();
	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		= 24; // (width, height) = (480, 480) --> numFrame = 24, divisible
	const FrameSequence frameSequence	= generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height);

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));

	for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++)
	{
		clearColorScreen(m_gl, clearColor);
		EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, DE_NULL, 0));

		for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
		{
			vector<EGLint>	damageRegion;
			int				bufferAge		= -1;
			int				startFrameNdx	= -1;
			int				endFrameNdx		= frameNdx;

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

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

			if (bufferAge == 0 || bufferAge > frameNdx)
			{
				clearColorScreen(m_gl, clearColor);
				startFrameNdx = 0;
			}
			else
				startFrameNdx = frameNdx-bufferAge+1;

			for (int ndx = startFrameNdx; ndx <= endFrameNdx; ndx++)
			{
				const vector<EGLint> partialDamageRegion = getDamageRegion(frameSequence[ndx]);

				damageRegion.insert(damageRegion.end(), partialDamageRegion.begin(), partialDamageRegion.end());
				m_gles2Renderer->render(width, height, frameSequence[ndx]);
			}

			EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
		}
	}
	return STOP;
}

// generate a frame sequence with certain frame for visual verification
FrameSequence generateFrameSequence (const vector<DrawType>& frameDrawType, de::Random& rnd, int numFrames, int width, int height)
{
	const int			frameDiff		= height / numFrames;
	const GLubyte		r				= rnd.getUint8();
	const GLubyte		g				= rnd.getUint8();
	const GLubyte		b				= rnd.getUint8();
	const Color			color			(r, g, b);
	FrameSequence		frameSequence;

	for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
	{
		Frame frame (width, height);

		for (int rectNdx = 0; rectNdx < (int)frameDrawType.size(); rectNdx++)
		{
			const int			rectHeight		= frameDiff / (int)frameDrawType.size();
			const ColoredRect	rect			(IVec2(0, frameNdx*frameDiff+rectNdx*rectHeight), IVec2(width, frameNdx*frameDiff+(rectNdx+1)*rectHeight), color);
			const DrawCommand	drawCommand		(frameDrawType[rectNdx], rect);

			frame.draws.push_back(drawCommand);
		}
		frameSequence.push_back(frame);
	}
	return frameSequence;
}

vector<EGLint> getDamageRegion (const Frame& frame)
{
	vector<EGLint> damageRegion;
	for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
	{
		const ColoredRect& rect = frame.draws[drawNdx].rect;
		damageRegion.push_back(rect.bottomLeft.x());
		damageRegion.push_back(rect.bottomLeft.y());
		damageRegion.push_back(rect.topRight.x() - rect.bottomLeft.x());
		damageRegion.push_back(rect.topRight.y() - rect.bottomLeft.y());
	}

	DE_ASSERT(damageRegion.size() % 4 == 0);
	return damageRegion;
}

string generateTestName (const vector<DrawType>& frameDrawType)
{
	std::ostringstream stream;

	for (size_t ndx = 0; ndx < frameDrawType.size(); ndx++)
	{
		if (frameDrawType[ndx] == DRAWTYPE_GLES2_RENDER)
			stream << "render";
		else if (frameDrawType[ndx] == DRAWTYPE_GLES2_CLEAR)
			stream << "clear";
		else
			DE_ASSERT(false);

		if (ndx < frameDrawType.size()-1)
			stream << "_";
	}

	return stream.str();
}

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 preserveBuffer)
{
	eglu::FilterList filters;

	filters << isWindow << isES2Renderable;
	if (preserveBuffer)
		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);
}

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

} // anonymous

SwapBuffersWithDamageTests::SwapBuffersWithDamageTests (EglTestContext& eglTestCtx)
	: TestCaseGroup(eglTestCtx, "swap_buffers_with_damage", "Swap buffers with damages tests")
{
}

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

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

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

	for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++)
	{
		string name = generateTestName(frameDrawTypes[drawTypeNdx]);
		addChild(new SwapBuffersWithDamageTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, name.c_str(), ""));
	}

	for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++)
	{
		string name = "preserve_buffer_" + generateTestName(frameDrawTypes[drawTypeNdx]);
		addChild(new SwapBuffersWithDamageAndPreserveBufferTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, name.c_str(), ""));
	}

	for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++)
	{
		string name = "buffer_age_" + generateTestName(frameDrawTypes[drawTypeNdx]);
		addChild(new SwapBuffersWithDamageAndBufferAgeTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, name.c_str(), ""));
	}
}

} // egl
} // deqp
