/*-------------------------------------------------------------------------
 * 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
};

enum ResizeType
{
	RESIZETYPE_NONE = 0,
	RESIZETYPE_BEFORE_SWAP,
	RESIZETYPE_AFTER_SWAP,

	RESIZETYPE_LAST
};

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,
																 ResizeType					resizeType,
																 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;
	const ResizeType			m_resizeType;
	EGLDisplay					m_eglDisplay;
	EGLSurface					m_eglSurface;
	glw::Functions				m_gl;
	GLES2Renderer*				m_gles2Renderer;
};

SwapBuffersWithDamageTest::SwapBuffersWithDamageTest (EglTestContext& eglTestCtx, const vector<DrawType>& frameDrawType, int iterationTimes, ResizeType resizeType, 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_resizeType		(resizeType)
	, 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]);

			if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
			{
				if (currentFrameNdx % 2 == 0)
					m_window->setSurfaceSize(IVec2(width*2, height/2));
				else
					m_window->setSurfaceSize(IVec2(height/2, width*2));
			}

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

			if (m_resizeType == RESIZETYPE_AFTER_SWAP)
			{
				if (currentFrameNdx % 2 == 0)
					m_window->setSurfaceSize(IVec2(width*2, height/2));
				else
					m_window->setSurfaceSize(IVec2(height/2, width*2));
			}
		}
	}
	return STOP;
}

class SwapBuffersWithDamageAndPreserveBufferTest : public SwapBuffersWithDamageTest
{
public:
					SwapBuffersWithDamageAndPreserveBufferTest	(EglTestContext&			eglTestCtx,
																 const vector<DrawType>&	frameDrawType,
																 int						iterationTimes,
																 ResizeType					resizeType,
																 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,
																						ResizeType				resizeType,
																						const char*				name,
																						const char*				description)
	: SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, resizeType, 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);

			if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
			{
				if (frameNdx % 2 == 0)
					m_window->setSurfaceSize(IVec2(width*2, height/2));
				else
					m_window->setSurfaceSize(IVec2(height/2, width*2));
			}

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

			if (m_resizeType == RESIZETYPE_AFTER_SWAP)
			{
				if (frameNdx % 2 == 0)
					m_window->setSurfaceSize(IVec2(width*2, height/2));
				else
					m_window->setSurfaceSize(IVec2(height/2, width*2));
			}
		}
	}

	return STOP;
}

class SwapBuffersWithDamageAndBufferAgeTest : public SwapBuffersWithDamageTest
{
public:
					SwapBuffersWithDamageAndBufferAgeTest	(EglTestContext&			eglTestCtx,
															 const vector<DrawType>&	frameDrawType,
															 int						iterationTimes,
															 ResizeType					resizeType,
															 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,
																			  ResizeType				resizeType,
																			  const char*				name,
																			  const char*				description)
	: SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, resizeType, 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]);
			}

			if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
			{
				if (frameNdx % 2 == 0)
					m_window->setSurfaceSize(IVec2(width*2, height/2));
				else
					m_window->setSurfaceSize(IVec2(height/2, width*2));
			}

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

			if (m_resizeType == RESIZETYPE_AFTER_SWAP)
			{
				if (frameNdx % 2 == 0)
					m_window->setSurfaceSize(IVec2(width*2, height/2));
				else
					m_window->setSurfaceSize(IVec2(height/2, width*2));
			}
		}
	}
	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();
}

string generateResizeGroupName (ResizeType resizeType)
{
	switch (resizeType)
	{
		case RESIZETYPE_NONE:
			return "no_resize";

		case RESIZETYPE_AFTER_SWAP:
			return "resize_after_swap";

		case RESIZETYPE_BEFORE_SWAP:
			return "resize_before_swap";

		default:
			DE_FATAL("Unknown resize type");
			return "";
	}
}

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
	};

	const ResizeType resizeTypes[] =
	{
		RESIZETYPE_NONE,
		RESIZETYPE_BEFORE_SWAP,
		RESIZETYPE_AFTER_SWAP
	};

	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 resizeTypeNdx = 0; resizeTypeNdx < DE_LENGTH_OF_ARRAY(resizeTypes); resizeTypeNdx++)
	{
		const ResizeType		resizeType	= resizeTypes[resizeTypeNdx];
		TestCaseGroup* const	resizeGroup	= new TestCaseGroup(m_eglTestCtx, generateResizeGroupName(resizeType).c_str(), "");

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

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

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

		addChild(resizeGroup);
	}
}

} // egl
} // deqp
