/*-------------------------------------------------------------------------
 * drawElements Quality Program EGL Module
 * ---------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Rendering tests for different config and api combinations.
 * \todo [2013-03-19 pyry] GLES1 and VG support.
 *//*--------------------------------------------------------------------*/

#include "teglRenderTests.hpp"
#include "teglRenderCase.hpp"

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

#include "egluDefs.hpp"
#include "egluUtil.hpp"

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

#include "gluShaderProgram.hpp"

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

#include "deRandom.hpp"
#include "deSharedPtr.hpp"
#include "deSemaphore.hpp"
#include "deThread.hpp"
#include "deString.h"

#include "rrRenderer.hpp"
#include "rrFragmentOperations.hpp"

#include <algorithm>
#include <iterator>
#include <memory>
#include <set>

namespace deqp
{
namespace egl
{

using std::string;
using std::vector;
using std::set;

using tcu::Vec4;

using tcu::TestLog;

using namespace glw;
using namespace eglw;

static const tcu::Vec4	CLEAR_COLOR		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
static const float		CLEAR_DEPTH		= 1.0f;
static const int		CLEAR_STENCIL	= 0;

namespace
{

enum PrimitiveType
{
	PRIMITIVETYPE_TRIANGLE = 0,	//!< Triangles, requires 3 coordinates per primitive
//	PRIMITIVETYPE_POINT,		//!< Points, requires 1 coordinate per primitive (w is used as size)
//	PRIMITIVETYPE_LINE,			//!< Lines, requires 2 coordinates per primitive

	PRIMITIVETYPE_LAST
};

enum BlendMode
{
	BLENDMODE_NONE = 0,			//!< No blending
	BLENDMODE_ADDITIVE,			//!< Blending with ONE, ONE
	BLENDMODE_SRC_OVER,			//!< Blending with SRC_ALPHA, ONE_MINUS_SRC_ALPHA

	BLENDMODE_LAST
};

enum DepthMode
{
	DEPTHMODE_NONE = 0,			//!< No depth test or depth writes
	DEPTHMODE_LESS,				//!< Depth test with less & depth write

	DEPTHMODE_LAST
};

enum StencilMode
{
	STENCILMODE_NONE = 0,		//!< No stencil test or write
	STENCILMODE_LEQUAL_INC,		//!< Stencil test with LEQUAL, increment on pass

	STENCILMODE_LAST
};

struct DrawPrimitiveOp
{
	PrimitiveType	type;
	int				count;
	vector<Vec4>	positions;
	vector<Vec4>	colors;
	BlendMode		blend;
	DepthMode		depth;
	StencilMode		stencil;
	int				stencilRef;
};

static bool isANarrowScreenSpaceTriangle (const tcu::Vec4& p0, const tcu::Vec4& p1, const tcu::Vec4& p2)
{
	// to clip space
	const tcu::Vec2	csp0				= p0.swizzle(0, 1) / p0.w();
	const tcu::Vec2	csp1				= p1.swizzle(0, 1) / p1.w();
	const tcu::Vec2	csp2				= p2.swizzle(0, 1) / p2.w();

	const tcu::Vec2	e01					= (csp1 - csp0);
	const tcu::Vec2	e02					= (csp2 - csp0);

	const float		minimumVisibleArea	= 0.4f; // must cover at least 10% of the surface
	const float		visibleArea			= de::abs(e01.x() * e02.y() - e02.x() * e01.y()) * 0.5f;

	return visibleArea < minimumVisibleArea;
}

void randomizeDrawOp (de::Random& rnd, DrawPrimitiveOp& drawOp, const bool alphaZeroOrOne)
{
	const int	minStencilRef	= 0;
	const int	maxStencilRef	= 8;
	const int	minPrimitives	= 2;
	const int	maxPrimitives	= 4;

	const float	maxTriOffset	= 1.0f;
	const float	minDepth		= -1.0f; // \todo [pyry] Reference doesn't support Z clipping yet
	const float	maxDepth		= 1.0f;

	const float	minRGB			= 0.2f;
	const float	maxRGB			= 0.9f;
	const float	minAlpha		= 0.3f;
	const float	maxAlpha		= 1.0f;

	drawOp.type			= (PrimitiveType)rnd.getInt(0, PRIMITIVETYPE_LAST-1);
	drawOp.count		= rnd.getInt(minPrimitives, maxPrimitives);
	drawOp.blend		= (BlendMode)rnd.getInt(0, BLENDMODE_LAST-1);
	drawOp.depth		= (DepthMode)rnd.getInt(0, DEPTHMODE_LAST-1);
	drawOp.stencil		= (StencilMode)rnd.getInt(0, STENCILMODE_LAST-1);
	drawOp.stencilRef	= rnd.getInt(minStencilRef, maxStencilRef);

	if (drawOp.type == PRIMITIVETYPE_TRIANGLE)
	{
		drawOp.positions.resize(drawOp.count*3);
		drawOp.colors.resize(drawOp.count*3);

		for (int triNdx = 0; triNdx < drawOp.count; triNdx++)
		{
			const float		cx		= rnd.getFloat(-1.0f, 1.0f);
			const float		cy		= rnd.getFloat(-1.0f, 1.0f);
			const float		flatAlpha = (rnd.getFloat(minAlpha, maxAlpha) > 0.5f) ? 1.0f : 0.0f;

			for (int coordNdx = 0; coordNdx < 3; coordNdx++)
			{
				tcu::Vec4&	position	= drawOp.positions[triNdx*3 + coordNdx];
				tcu::Vec4&	color		= drawOp.colors[triNdx*3 + coordNdx];

				position.x()	= cx + rnd.getFloat(-maxTriOffset, maxTriOffset);
				position.y()	= cy + rnd.getFloat(-maxTriOffset, maxTriOffset);
				position.z()	= rnd.getFloat(minDepth, maxDepth);
				position.w()	= 1.0f;

				color.x()		= rnd.getFloat(minRGB, maxRGB);
				color.y()		= rnd.getFloat(minRGB, maxRGB);
				color.z()		= rnd.getFloat(minRGB, maxRGB);
				color.w()		= rnd.getFloat(minAlpha, maxAlpha);

				if (alphaZeroOrOne)
				{
					color.w()	= flatAlpha;
				}
			}

			// avoid generating narrow triangles
			{
				const int	maxAttempts	= 100;
				int			numAttempts	= 0;
				tcu::Vec4&	p0			= drawOp.positions[triNdx*3 + 0];
				tcu::Vec4&	p1			= drawOp.positions[triNdx*3 + 1];
				tcu::Vec4&	p2			= drawOp.positions[triNdx*3 + 2];

				while (isANarrowScreenSpaceTriangle(p0, p1, p2))
				{
					p1.x()	= cx + rnd.getFloat(-maxTriOffset, maxTriOffset);
					p1.y()	= cy + rnd.getFloat(-maxTriOffset, maxTriOffset);
					p1.z()	= rnd.getFloat(minDepth, maxDepth);
					p1.w()	= 1.0f;

					p2.x()	= cx + rnd.getFloat(-maxTriOffset, maxTriOffset);
					p2.y()	= cy + rnd.getFloat(-maxTriOffset, maxTriOffset);
					p2.z()	= rnd.getFloat(minDepth, maxDepth);
					p2.w()	= 1.0f;

					if (++numAttempts > maxAttempts)
					{
						DE_ASSERT(false);
						break;
					}
				}
			}
		}
	}
	else
		DE_ASSERT(false);
}

// Reference rendering code

class ReferenceShader : public rr::VertexShader, public rr::FragmentShader
{
public:
	enum
	{
		VaryingLoc_Color = 0
	};

	ReferenceShader ()
		: rr::VertexShader	(2, 1)		// color and pos in => color out
		, rr::FragmentShader(1, 1)		// color in => color out
	{
		this->rr::VertexShader::m_inputs[0].type		= rr::GENERICVECTYPE_FLOAT;
		this->rr::VertexShader::m_inputs[1].type		= rr::GENERICVECTYPE_FLOAT;

		this->rr::VertexShader::m_outputs[0].type		= rr::GENERICVECTYPE_FLOAT;
		this->rr::VertexShader::m_outputs[0].flatshade	= false;

		this->rr::FragmentShader::m_inputs[0].type		= rr::GENERICVECTYPE_FLOAT;
		this->rr::FragmentShader::m_inputs[0].flatshade	= false;

		this->rr::FragmentShader::m_outputs[0].type		= rr::GENERICVECTYPE_FLOAT;
	}

	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
	{
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		{
			const int positionAttrLoc = 0;
			const int colorAttrLoc = 1;

			rr::VertexPacket& packet = *packets[packetNdx];

			// Transform to position
			packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx);

			// Pass color to FS
			packet.outputs[VaryingLoc_Color] = rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx);
		}
	}

	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
	{
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		{
			rr::FragmentPacket& packet = packets[packetNdx];

			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packet, context, VaryingLoc_Color, fragNdx));
		}
	}
};

void toReferenceRenderState (rr::RenderState& state, const DrawPrimitiveOp& drawOp)
{
	state.cullMode	= rr::CULLMODE_NONE;

	if (drawOp.blend != BLENDMODE_NONE)
	{
		state.fragOps.blendMode = rr::BLENDMODE_STANDARD;

		switch (drawOp.blend)
		{
			case BLENDMODE_ADDITIVE:
				state.fragOps.blendRGBState.srcFunc		= rr::BLENDFUNC_ONE;
				state.fragOps.blendRGBState.dstFunc		= rr::BLENDFUNC_ONE;
				state.fragOps.blendRGBState.equation	= rr::BLENDEQUATION_ADD;
				state.fragOps.blendAState				= state.fragOps.blendRGBState;
				break;

			case BLENDMODE_SRC_OVER:
				state.fragOps.blendRGBState.srcFunc		= rr::BLENDFUNC_SRC_ALPHA;
				state.fragOps.blendRGBState.dstFunc		= rr::BLENDFUNC_ONE_MINUS_SRC_ALPHA;
				state.fragOps.blendRGBState.equation	= rr::BLENDEQUATION_ADD;
				state.fragOps.blendAState				= state.fragOps.blendRGBState;
				break;

			default:
				DE_ASSERT(false);
		}
	}

	if (drawOp.depth != DEPTHMODE_NONE)
	{
		state.fragOps.depthTestEnabled = true;

		DE_ASSERT(drawOp.depth == DEPTHMODE_LESS);
		state.fragOps.depthFunc = rr::TESTFUNC_LESS;
	}

	if (drawOp.stencil != STENCILMODE_NONE)
	{
		state.fragOps.stencilTestEnabled = true;

		DE_ASSERT(drawOp.stencil == STENCILMODE_LEQUAL_INC);
		state.fragOps.stencilStates[0].func		= rr::TESTFUNC_LEQUAL;
		state.fragOps.stencilStates[0].sFail	= rr::STENCILOP_KEEP;
		state.fragOps.stencilStates[0].dpFail	= rr::STENCILOP_INCR;
		state.fragOps.stencilStates[0].dpPass	= rr::STENCILOP_INCR;
		state.fragOps.stencilStates[0].ref		= drawOp.stencilRef;
		state.fragOps.stencilStates[1]			= state.fragOps.stencilStates[0];
	}
}

tcu::TextureFormat getColorFormat (const tcu::PixelFormat& colorBits)
{
	using tcu::TextureFormat;

	DE_ASSERT(de::inBounds(colorBits.redBits,	0, 0xff) &&
			  de::inBounds(colorBits.greenBits,	0, 0xff) &&
			  de::inBounds(colorBits.blueBits,	0, 0xff) &&
			  de::inBounds(colorBits.alphaBits,	0, 0xff));

#define PACK_FMT(R, G, B, A) (((R) << 24) | ((G) << 16) | ((B) << 8) | (A))

	// \note [pyry] This may not hold true on some implementations - best effort guess only.
	switch (PACK_FMT(colorBits.redBits, colorBits.greenBits, colorBits.blueBits, colorBits.alphaBits))
	{
		case PACK_FMT(8,8,8,8):		return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);
		case PACK_FMT(8,8,8,0):		return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_INT8);
		case PACK_FMT(4,4,4,4):		return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_SHORT_4444);
		case PACK_FMT(5,5,5,1):		return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_SHORT_5551);
		case PACK_FMT(5,6,5,0):		return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_SHORT_565);

		// \note Defaults to RGBA8
		default:					return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);
	}

#undef PACK_FMT
}

/*
The getColorThreshold function is used to obtain a
threshold usable for the fuzzyCompare function.

For 8bit color depths a value of 0.02 should provide
a good metric for rejecting images above this level.
For other bit depths other thresholds should be selected.
Ideally this function would take advantage of the
getColorThreshold function provided by the PixelFormat class
as this would also allow setting per channel thresholds.
However using the PixelFormat provided function can result
in too strict thresholds for 8bit bit depths (compared to
the current default of 0.02) or too relaxed for lower bit
depths if scaled proportionally to the 8bit default.
*/

float getColorThreshold (const tcu::PixelFormat& colorBits)
{
	if ((colorBits.redBits > 0 && colorBits.redBits < 8) ||
		(colorBits.greenBits > 0 && colorBits.greenBits < 8) ||
		(colorBits.blueBits > 0 && colorBits.blueBits < 8) ||
		(colorBits.alphaBits > 0 && colorBits.alphaBits < 8))
	{
		return 0.05f;
	}
	else
	{
		return 0.02f;
	}
}

tcu::TextureFormat getDepthFormat (const int depthBits)
{
	switch (depthBits)
	{
		case 0:		return tcu::TextureFormat();
		case 8:		return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
		case 16:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
		case 24:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT24);
		case 32:
		default:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
	}
}

tcu::TextureFormat getStencilFormat (int stencilBits)
{
	switch (stencilBits)
	{
		case 0:		return tcu::TextureFormat();
		case 8:
		default:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
	}
}

void renderReference (const tcu::PixelBufferAccess& dst, const vector<DrawPrimitiveOp>& drawOps, const tcu::PixelFormat& colorBits, const int depthBits, const int stencilBits, const int numSamples, const int subpixelBits)
{
	const int						width			= dst.getWidth();
	const int						height			= dst.getHeight();

	tcu::TextureLevel				colorBuffer;
	tcu::TextureLevel				depthBuffer;
	tcu::TextureLevel				stencilBuffer;

	rr::Renderer					referenceRenderer;
	rr::VertexAttrib				attributes[2];
	const ReferenceShader			shader;

	attributes[0].type				= rr::VERTEXATTRIBTYPE_FLOAT;
	attributes[0].size				= 4;
	attributes[0].stride			= 0;
	attributes[0].instanceDivisor	= 0;

	attributes[1].type				= rr::VERTEXATTRIBTYPE_FLOAT;
	attributes[1].size				= 4;
	attributes[1].stride			= 0;
	attributes[1].instanceDivisor	= 0;

	// Initialize buffers.
	colorBuffer.setStorage(getColorFormat(colorBits), numSamples, width, height);
	rr::clearMultisampleColorBuffer(colorBuffer, CLEAR_COLOR, rr::WindowRectangle(0, 0, width, height));

	if (depthBits > 0)
	{
		depthBuffer.setStorage(getDepthFormat(depthBits), numSamples, width, height);
		rr::clearMultisampleDepthBuffer(depthBuffer, CLEAR_DEPTH, rr::WindowRectangle(0, 0, width, height));
	}

	if (stencilBits > 0)
	{
		stencilBuffer.setStorage(getStencilFormat(stencilBits), numSamples, width, height);
		rr::clearMultisampleStencilBuffer(stencilBuffer, CLEAR_STENCIL, rr::WindowRectangle(0, 0, width, height));
	}

	const rr::RenderTarget renderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer.getAccess()),
										rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer.getAccess()),
										rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer.getAccess()));

	for (vector<DrawPrimitiveOp>::const_iterator drawOp = drawOps.begin(); drawOp != drawOps.end(); drawOp++)
	{
		// Translate state
		rr::RenderState renderState((rr::ViewportState)(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer.getAccess())), subpixelBits);
		toReferenceRenderState(renderState, *drawOp);

		DE_ASSERT(drawOp->type == PRIMITIVETYPE_TRIANGLE);

		attributes[0].pointer = &drawOp->positions[0];
		attributes[1].pointer = &drawOp->colors[0];

		referenceRenderer.draw(
			rr::DrawCommand(
				renderState,
				renderTarget,
				rr::Program(static_cast<const rr::VertexShader*>(&shader), static_cast<const rr::FragmentShader*>(&shader)),
				2,
				attributes,
				rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, drawOp->count * 3, 0)));
	}

	rr::resolveMultisampleColorBuffer(dst, rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer.getAccess()));
}

// API rendering code

class Program
{
public:
					Program				(void) {}
	virtual			~Program			(void) {}

	virtual void	setup				(void) const = DE_NULL;
};

typedef de::SharedPtr<Program> ProgramSp;

static glu::ProgramSources getProgramSourcesES2 (void)
{
	static const char* s_vertexSrc =
		"attribute highp vec4 a_position;\n"
		"attribute mediump vec4 a_color;\n"
		"varying mediump vec4 v_color;\n"
		"void main (void)\n"
		"{\n"
		"	gl_Position = a_position;\n"
		"	v_color = a_color;\n"
		"}\n";

	static const char* s_fragmentSrc =
		"varying mediump vec4 v_color;\n"
		"void main (void)\n"
		"{\n"
		"	gl_FragColor = v_color;\n"
		"}\n";

	return glu::ProgramSources() << glu::VertexSource(s_vertexSrc) << glu::FragmentSource(s_fragmentSrc);
}

class GLES2Program : public Program
{
public:
	GLES2Program (const glw::Functions& gl)
		: m_gl				(gl)
		, m_program			(gl, getProgramSourcesES2())
		, m_positionLoc		(0)
		, m_colorLoc		(0)
	{

		m_positionLoc	= m_gl.getAttribLocation(m_program.getProgram(), "a_position");
		m_colorLoc		= m_gl.getAttribLocation(m_program.getProgram(), "a_color");
	}

	~GLES2Program (void)
	{
	}

	void setup (void) const
	{
		m_gl.useProgram(m_program.getProgram());
		m_gl.enableVertexAttribArray(m_positionLoc);
		m_gl.enableVertexAttribArray(m_colorLoc);
		GLU_CHECK_GLW_MSG(m_gl, "Program setup failed");
	}

	int						getPositionLoc		(void) const { return m_positionLoc;	}
	int						getColorLoc			(void) const { return m_colorLoc;		}

private:
	const glw::Functions&	m_gl;
	glu::ShaderProgram		m_program;
	int						m_positionLoc;
	int						m_colorLoc;
};

void clearGLES2 (const glw::Functions& gl, const tcu::Vec4& color, const float depth, const int stencil)
{
	gl.clearColor(color.x(), color.y(), color.z(), color.w());
	gl.clearDepthf(depth);
	gl.clearStencil(stencil);
	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
}

void drawGLES2 (const glw::Functions& gl, const Program& program, const DrawPrimitiveOp& drawOp)
{
	const GLES2Program& gles2Program = dynamic_cast<const GLES2Program&>(program);

	switch (drawOp.blend)
	{
		case BLENDMODE_NONE:
			gl.disable(GL_BLEND);
			break;

		case BLENDMODE_ADDITIVE:
			gl.enable(GL_BLEND);
			gl.blendFunc(GL_ONE, GL_ONE);
			break;

		case BLENDMODE_SRC_OVER:
			gl.enable(GL_BLEND);
			gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			break;

		default:
			DE_ASSERT(false);
	}

	switch (drawOp.depth)
	{
		case DEPTHMODE_NONE:
			gl.disable(GL_DEPTH_TEST);
			break;

		case DEPTHMODE_LESS:
			gl.enable(GL_DEPTH_TEST);
			break;

		default:
			DE_ASSERT(false);
	}

	switch (drawOp.stencil)
	{
		case STENCILMODE_NONE:
			gl.disable(GL_STENCIL_TEST);
			break;

		case STENCILMODE_LEQUAL_INC:
			gl.enable(GL_STENCIL_TEST);
			gl.stencilFunc(GL_LEQUAL, drawOp.stencilRef, ~0u);
			gl.stencilOp(GL_KEEP, GL_INCR, GL_INCR);
			break;

		default:
			DE_ASSERT(false);
	}

	gl.disable(GL_DITHER);

	gl.vertexAttribPointer(gles2Program.getPositionLoc(), 4, GL_FLOAT, GL_FALSE, 0, &drawOp.positions[0]);
	gl.vertexAttribPointer(gles2Program.getColorLoc(), 4, GL_FLOAT, GL_FALSE, 0, &drawOp.colors[0]);

	DE_ASSERT(drawOp.type == PRIMITIVETYPE_TRIANGLE);
	gl.drawArrays(GL_TRIANGLES, 0, drawOp.count*3);
}

static void readPixelsGLES2 (const glw::Functions& gl, tcu::Surface& dst)
{
	gl.readPixels(0, 0, dst.getWidth(), dst.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr());
}

Program* createProgram (const glw::Functions& gl, EGLint api)
{
	switch (api)
	{
		case EGL_OPENGL_ES2_BIT:		return new GLES2Program(gl);
		case EGL_OPENGL_ES3_BIT_KHR:	return new GLES2Program(gl);
		default:
			throw tcu::NotSupportedError("Unsupported API");
	}
}

void draw (const glw::Functions& gl, EGLint api, const Program& program, const DrawPrimitiveOp& drawOp)
{
	switch (api)
	{
		case EGL_OPENGL_ES2_BIT:		drawGLES2(gl, program, drawOp);		break;
		case EGL_OPENGL_ES3_BIT_KHR:	drawGLES2(gl, program, drawOp);		break;
		default:
			throw tcu::NotSupportedError("Unsupported API");
	}
}

void clear (const glw::Functions& gl, EGLint api, const tcu::Vec4& color, const float depth, const int stencil)
{
	switch (api)
	{
		case EGL_OPENGL_ES2_BIT:		clearGLES2(gl, color, depth, stencil);		break;
		case EGL_OPENGL_ES3_BIT_KHR:	clearGLES2(gl, color, depth, stencil);		break;
		default:
			throw tcu::NotSupportedError("Unsupported API");
	}
}

static void readPixels (const glw::Functions& gl, EGLint api, tcu::Surface& dst)
{
	switch (api)
	{
		case EGL_OPENGL_ES2_BIT:		readPixelsGLES2(gl, dst);		break;
		case EGL_OPENGL_ES3_BIT_KHR:	readPixelsGLES2(gl, dst);		break;
		default:
			throw tcu::NotSupportedError("Unsupported API");
	}
}

static void finish (const glw::Functions& gl, EGLint api)
{
	switch (api)
	{
		case EGL_OPENGL_ES2_BIT:
		case EGL_OPENGL_ES3_BIT_KHR:
			gl.finish();
			break;

		default:
			throw tcu::NotSupportedError("Unsupported API");
	}
}

tcu::PixelFormat getPixelFormat (const Library& egl, EGLDisplay display, EGLConfig config)
{
	tcu::PixelFormat fmt;
	fmt.redBits		= eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE);
	fmt.greenBits	= eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE);
	fmt.blueBits	= eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE);
	fmt.alphaBits	= eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE);
	return fmt;
}

} // anonymous

// SingleThreadRenderCase

class SingleThreadRenderCase : public MultiContextRenderCase
{
public:
						SingleThreadRenderCase		(EglTestContext& eglTestCtx, const char* name, const char* description, EGLint api, EGLint surfaceType, const eglu::FilterList& filters, int numContextsPerApi);

	void				init						(void);

private:
	virtual void		executeForContexts			(EGLDisplay display, EGLSurface surface, const Config& config, const std::vector<std::pair<EGLint, EGLContext> >& contexts);

	glw::Functions		m_gl;
};

// SingleThreadColorClearCase

SingleThreadRenderCase::SingleThreadRenderCase (EglTestContext& eglTestCtx, const char* name, const char* description, EGLint api, EGLint surfaceType, const eglu::FilterList& filters, int numContextsPerApi)
	: MultiContextRenderCase(eglTestCtx, name, description, api, surfaceType, filters, numContextsPerApi)
{
}

void SingleThreadRenderCase::init (void)
{
	MultiContextRenderCase::init();
	m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
}

void SingleThreadRenderCase::executeForContexts (EGLDisplay display, EGLSurface surface, const Config& config, const std::vector<std::pair<EGLint, EGLContext> >& contexts)
{
	const Library&			egl			= m_eglTestCtx.getLibrary();
	const int				width		= eglu::querySurfaceInt(egl, display, surface, EGL_WIDTH);
	const int				height		= eglu::querySurfaceInt(egl, display, surface, EGL_HEIGHT);
	const int				numContexts	= (int)contexts.size();
	const int				drawsPerCtx	= 2;
	const int				numIters	= 2;
	const tcu::PixelFormat	pixelFmt	= getPixelFormat(egl, display, config.config);
	const float				threshold	= getColorThreshold(pixelFmt);

	const int				depthBits	= eglu::getConfigAttribInt(egl, display, config.config, EGL_DEPTH_SIZE);
	const int				stencilBits	= eglu::getConfigAttribInt(egl, display, config.config, EGL_STENCIL_SIZE);
	const int				numSamples	= eglu::getConfigAttribInt(egl, display, config.config, EGL_SAMPLES);

	TestLog&				log			= m_testCtx.getLog();

	tcu::Surface			refFrame	(width, height);
	tcu::Surface			frame		(width, height);

	de::Random				rnd			(deStringHash(getName()) ^ deInt32Hash(numContexts));
	vector<ProgramSp>		programs	(contexts.size());
	vector<DrawPrimitiveOp>	drawOps;

	// Log basic information about config.
	log << TestLog::Message << "EGL_RED_SIZE = "		<< pixelFmt.redBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_GREEN_SIZE = "		<< pixelFmt.greenBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_BLUE_SIZE = "		<< pixelFmt.blueBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_ALPHA_SIZE = "		<< pixelFmt.alphaBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_DEPTH_SIZE = "		<< depthBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_STENCIL_SIZE = "	<< stencilBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_SAMPLES = "			<< numSamples << TestLog::EndMessage;

	// Generate draw ops.
	drawOps.resize(numContexts*drawsPerCtx*numIters);
	for (vector<DrawPrimitiveOp>::iterator drawOp = drawOps.begin(); drawOp != drawOps.end(); ++drawOp)
		randomizeDrawOp(rnd, *drawOp, (pixelFmt.alphaBits == 1));

	// Create and setup programs per context
	for (int ctxNdx = 0; ctxNdx < numContexts; ctxNdx++)
	{
		EGLint		api			= contexts[ctxNdx].first;
		EGLContext	context		= contexts[ctxNdx].second;

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

		programs[ctxNdx] = ProgramSp(createProgram(m_gl, api));
		programs[ctxNdx]->setup();
	}

	// Clear to black using first context.
	{
		EGLint		api			= contexts[0].first;
		EGLContext	context		= contexts[0].second;

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

		clear(m_gl, api, CLEAR_COLOR, CLEAR_DEPTH, CLEAR_STENCIL);
		finish(m_gl, api);
	}

	// Render.
	for (int iterNdx = 0; iterNdx < numIters; iterNdx++)
	{
		for (int ctxNdx = 0; ctxNdx < numContexts; ctxNdx++)
		{
			EGLint		api			= contexts[ctxNdx].first;
			EGLContext	context		= contexts[ctxNdx].second;

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

			for (int drawNdx = 0; drawNdx < drawsPerCtx; drawNdx++)
			{
				const DrawPrimitiveOp& drawOp = drawOps[iterNdx*numContexts*drawsPerCtx + ctxNdx*drawsPerCtx + drawNdx];
				draw(m_gl, api, *programs[ctxNdx], drawOp);
			}

			finish(m_gl, api);
		}
	}

	// Read pixels using first context. \todo [pyry] Randomize?
	{
		EGLint		api		= contexts[0].first;
		EGLContext	context	= contexts[0].second;

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

		readPixels(m_gl, api, frame);
	}

	int	subpixelBits = 0;
	m_gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);

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

	// Render reference.
	// \note Reference image is always generated using single-sampling.
	renderReference(refFrame.getAccess(), drawOps, pixelFmt, depthBits, stencilBits, 1, subpixelBits);

	// Compare images
	{
		bool imagesOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, frame, threshold, tcu::COMPARE_LOG_RESULT);

		if (!imagesOk)
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
	}
}

// MultiThreadRenderCase

class MultiThreadRenderCase : public MultiContextRenderCase
{
public:
						MultiThreadRenderCase		(EglTestContext& eglTestCtx, const char* name, const char* description, EGLint api, EGLint surfaceType, const eglu::FilterList& filters, int numContextsPerApi);

	void				init						(void);

private:
	virtual void		executeForContexts			(EGLDisplay display, EGLSurface surface, const Config& config, const std::vector<std::pair<EGLint, EGLContext> >& contexts);

	glw::Functions		m_gl;
};

class RenderTestThread;

typedef de::SharedPtr<RenderTestThread>	RenderTestThreadSp;
typedef de::SharedPtr<de::Semaphore>	SemaphoreSp;

struct DrawOpPacket
{
	DrawOpPacket (void)
		: drawOps	(DE_NULL)
		, numOps	(0)
	{
	}

	const DrawPrimitiveOp*	drawOps;
	int						numOps;
	SemaphoreSp				wait;
	SemaphoreSp				signal;
};

class RenderTestThread : public de::Thread
{
public:
	RenderTestThread (const Library& egl, EGLDisplay display, EGLSurface surface, EGLContext context, EGLint api, const glw::Functions& gl, const Program& program, const std::vector<DrawOpPacket>& packets)
		: m_egl		(egl)
		, m_display	(display)
		, m_surface	(surface)
		, m_context	(context)
		, m_api		(api)
		, m_gl		(gl)
		, m_program	(program)
		, m_packets	(packets)
	{
	}

	void run (void)
	{
		for (std::vector<DrawOpPacket>::const_iterator packetIter = m_packets.begin(); packetIter != m_packets.end(); packetIter++)
		{
			// Wait until it is our turn.
			packetIter->wait->decrement();

			// Acquire context.
			EGLU_CHECK_CALL(m_egl, makeCurrent(m_display, m_surface, m_surface, m_context));

			// Execute rendering.
			for (int ndx = 0; ndx < packetIter->numOps; ndx++)
				draw(m_gl, m_api, m_program, packetIter->drawOps[ndx]);

			finish(m_gl, m_api);

			// Release context.
			EGLU_CHECK_CALL(m_egl, makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));

			// Signal completion.
			packetIter->signal->increment();
		}
		m_egl.releaseThread();
	}

private:
	const Library&						m_egl;
	EGLDisplay							m_display;
	EGLSurface							m_surface;
	EGLContext							m_context;
	EGLint								m_api;
	const glw::Functions&				m_gl;
	const Program&						m_program;
	const std::vector<DrawOpPacket>&	m_packets;
};

MultiThreadRenderCase::MultiThreadRenderCase (EglTestContext& eglTestCtx, const char* name, const char* description, EGLint api, EGLint surfaceType, const eglu::FilterList& filters, int numContextsPerApi)
	: MultiContextRenderCase(eglTestCtx, name, description, api, surfaceType, filters, numContextsPerApi)
{
}

void MultiThreadRenderCase::init (void)
{
	MultiContextRenderCase::init();
	m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
}

void MultiThreadRenderCase::executeForContexts (EGLDisplay display, EGLSurface surface, const Config& config, const std::vector<std::pair<EGLint, EGLContext> >& contexts)
{
	const Library&			egl					= m_eglTestCtx.getLibrary();
	const int				width				= eglu::querySurfaceInt(egl, display, surface, EGL_WIDTH);
	const int				height				= eglu::querySurfaceInt(egl, display, surface, EGL_HEIGHT);
	const int				numContexts			= (int)contexts.size();
	const int				opsPerPacket		= 2;
	const int				packetsPerThread	= 2;
	const int				numThreads			= numContexts;
	const int				numPackets			= numThreads * packetsPerThread;
	const tcu::PixelFormat	pixelFmt			= getPixelFormat(egl, display, config.config);
	const float				threshold			= getColorThreshold(pixelFmt);

	const int				depthBits			= eglu::getConfigAttribInt(egl, display, config.config, EGL_DEPTH_SIZE);
	const int				stencilBits			= eglu::getConfigAttribInt(egl, display, config.config, EGL_STENCIL_SIZE);
	const int				numSamples			= eglu::getConfigAttribInt(egl, display, config.config, EGL_SAMPLES);

	TestLog&				log					= m_testCtx.getLog();

	tcu::Surface			refFrame			(width, height);
	tcu::Surface			frame				(width, height);

	de::Random				rnd					(deStringHash(getName()) ^ deInt32Hash(numContexts));

	// Resources that need cleanup
	vector<ProgramSp>				programs	(numContexts);
	vector<SemaphoreSp>				semaphores	(numPackets+1);
	vector<DrawPrimitiveOp>			drawOps		(numPackets*opsPerPacket);
	vector<vector<DrawOpPacket> >	packets		(numThreads);
	vector<RenderTestThreadSp>		threads		(numThreads);

	// Log basic information about config.
	log << TestLog::Message << "EGL_RED_SIZE = "		<< pixelFmt.redBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_GREEN_SIZE = "		<< pixelFmt.greenBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_BLUE_SIZE = "		<< pixelFmt.blueBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_ALPHA_SIZE = "		<< pixelFmt.alphaBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_DEPTH_SIZE = "		<< depthBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_STENCIL_SIZE = "	<< stencilBits << TestLog::EndMessage;
	log << TestLog::Message << "EGL_SAMPLES = "			<< numSamples << TestLog::EndMessage;

	// Initialize semaphores.
	for (vector<SemaphoreSp>::iterator sem = semaphores.begin(); sem != semaphores.end(); ++sem)
		*sem = SemaphoreSp(new de::Semaphore(0));

	// Create draw ops.
	for (vector<DrawPrimitiveOp>::iterator drawOp = drawOps.begin(); drawOp != drawOps.end(); ++drawOp)
		randomizeDrawOp(rnd, *drawOp, (pixelFmt.alphaBits == 1));

	// Create packets.
	for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
	{
		packets[threadNdx].resize(packetsPerThread);

		for (int packetNdx = 0; packetNdx < packetsPerThread; packetNdx++)
		{
			DrawOpPacket& packet = packets[threadNdx][packetNdx];

			// Threads take turns with packets.
			packet.wait		= semaphores[packetNdx*numThreads + threadNdx];
			packet.signal	= semaphores[packetNdx*numThreads + threadNdx + 1];
			packet.numOps	= opsPerPacket;
			packet.drawOps	= &drawOps[(packetNdx*numThreads + threadNdx)*opsPerPacket];
		}
	}

	// Create and setup programs per context
	for (int ctxNdx = 0; ctxNdx < numContexts; ctxNdx++)
	{
		EGLint		api			= contexts[ctxNdx].first;
		EGLContext	context		= contexts[ctxNdx].second;

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

		programs[ctxNdx] = ProgramSp(createProgram(m_gl, api));
		programs[ctxNdx]->setup();

		// Release context
		EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
	}

	// Clear to black using first context.
	{
		EGLint		api			= contexts[0].first;
		EGLContext	context		= contexts[0].second;

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

		clear(m_gl, api, CLEAR_COLOR, CLEAR_DEPTH, CLEAR_STENCIL);
		finish(m_gl, api);

		// Release context
		EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
	}

	// Create and launch threads (actual rendering starts once first semaphore is signaled).
	for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
	{
		threads[threadNdx] = RenderTestThreadSp(new RenderTestThread(egl, display, surface, contexts[threadNdx].second, contexts[threadNdx].first, m_gl, *programs[threadNdx], packets[threadNdx]));
		threads[threadNdx]->start();
	}

	// Signal start and wait until complete.
	semaphores.front()->increment();
	semaphores.back()->decrement();

	// Read pixels using first context. \todo [pyry] Randomize?
	{
		EGLint		api		= contexts[0].first;
		EGLContext	context	= contexts[0].second;

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

		readPixels(m_gl, api, frame);
	}

	int	subpixelBits = 0;
	m_gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);

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

	// Join threads.
	for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
		threads[threadNdx]->join();

	// Render reference.
	renderReference(refFrame.getAccess(), drawOps, pixelFmt, depthBits, stencilBits, 1, subpixelBits);

	// Compare images
	{
		bool imagesOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, frame, threshold, tcu::COMPARE_LOG_RESULT);

		if (!imagesOk)
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
	}
}

RenderTests::RenderTests (EglTestContext& eglTestCtx)
	: TestCaseGroup(eglTestCtx, "render", "Basic rendering with different client APIs")
{
}

RenderTests::~RenderTests (void)
{
}

struct RenderGroupSpec
{
	const char*			name;
	const char*			desc;
	EGLint				apiBits;
	eglu::ConfigFilter	baseFilter;
	int					numContextsPerApi;
};

template <deUint32 Bits>
static bool renderable (const eglu::CandidateConfig& c)
{
	return (c.renderableType() & Bits) == Bits;
}

template <class RenderClass>
static void createRenderGroups (EglTestContext& eglTestCtx, tcu::TestCaseGroup* group, const RenderGroupSpec* first, const RenderGroupSpec* last)
{
	for (const RenderGroupSpec* groupIter = first; groupIter != last; groupIter++)
	{
		tcu::TestCaseGroup* configGroup = new tcu::TestCaseGroup(eglTestCtx.getTestContext(), groupIter->name, groupIter->desc);
		group->addChild(configGroup);

		vector<RenderFilterList>	filterLists;
		eglu::FilterList			baseFilters;
		baseFilters << groupIter->baseFilter;
		getDefaultRenderFilterLists(filterLists, baseFilters);

		for (vector<RenderFilterList>::const_iterator listIter = filterLists.begin(); listIter != filterLists.end(); listIter++)
			configGroup->addChild(new RenderClass(eglTestCtx, listIter->getName(), "", groupIter->apiBits, listIter->getSurfaceTypeMask(), *listIter, groupIter->numContextsPerApi));
	}
}

void RenderTests::init (void)
{
	static const RenderGroupSpec singleContextCases[] =
	{
		{
			"gles2",
			"Primitive rendering using GLES2",
			EGL_OPENGL_ES2_BIT,
			renderable<EGL_OPENGL_ES2_BIT>,
			1
		},
		{
			"gles3",
			"Primitive rendering using GLES3",
			EGL_OPENGL_ES3_BIT,
			renderable<EGL_OPENGL_ES3_BIT>,
			1
		},
	};

	static const RenderGroupSpec multiContextCases[] =
	{
		{
			"gles2",
			"Primitive rendering using multiple GLES2 contexts to shared surface",
			EGL_OPENGL_ES2_BIT,
			renderable<EGL_OPENGL_ES2_BIT>,
			3
		},
		{
			"gles3",
			"Primitive rendering using multiple GLES3 contexts to shared surface",
			EGL_OPENGL_ES3_BIT,
			renderable<EGL_OPENGL_ES3_BIT>,
			3
		},
		{
			"gles2_gles3",
			"Primitive rendering using multiple APIs to shared surface",
			EGL_OPENGL_ES2_BIT|EGL_OPENGL_ES3_BIT,
			renderable<EGL_OPENGL_ES2_BIT|EGL_OPENGL_ES3_BIT>,
			1
		},
	};

	tcu::TestCaseGroup* singleContextGroup = new tcu::TestCaseGroup(m_testCtx, "single_context", "Single-context rendering");
	addChild(singleContextGroup);
	createRenderGroups<SingleThreadRenderCase>(m_eglTestCtx, singleContextGroup, &singleContextCases[0], &singleContextCases[DE_LENGTH_OF_ARRAY(singleContextCases)]);

	tcu::TestCaseGroup* multiContextGroup = new tcu::TestCaseGroup(m_testCtx, "multi_context", "Multi-context rendering with shared surface");
	addChild(multiContextGroup);
	createRenderGroups<SingleThreadRenderCase>(m_eglTestCtx, multiContextGroup, &multiContextCases[0], &multiContextCases[DE_LENGTH_OF_ARRAY(multiContextCases)]);

	tcu::TestCaseGroup* multiThreadGroup = new tcu::TestCaseGroup(m_testCtx, "multi_thread", "Multi-thread rendering with shared surface");
	addChild(multiThreadGroup);
	createRenderGroups<MultiThreadRenderCase>(m_eglTestCtx, multiThreadGroup, &multiContextCases[0], &multiContextCases[DE_LENGTH_OF_ARRAY(multiContextCases)]);
}

} // egl
} // deqp
