/*-------------------------------------------------------------------------
 * 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 Color clear case.
 *//*--------------------------------------------------------------------*/

#include "teglColorClearCase.hpp"
#include "tcuTestLog.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"
#include "egluUtil.hpp"
#include "deRandom.hpp"
#include "deString.h"
#include "tcuImageCompare.hpp"
#include "tcuVector.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuPixelFormat.hpp"
#include "glwFunctions.hpp"
#include "deThread.hpp"
#include "deSemaphore.hpp"
#include "deSharedPtr.hpp"
#include "teglGLES1RenderUtil.hpp"
#include "teglGLES2RenderUtil.hpp"
#include "teglVGRenderUtil.hpp"

#include <memory>
#include <iterator>

namespace deqp
{
namespace egl
{

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

// Utilities.

struct ClearOp
{
	ClearOp (int x_, int y_, int width_, int height_, const tcu::RGBA& color_)
		: x			(x_)
		, y			(y_)
		, width		(width_)
		, height	(height_)
		, color		(color_)
	{
	}

	ClearOp (void)
		: x			(0)
		, y			(0)
		, width		(0)
		, height	(0)
		, color		(0)
	{
	}

	int			x;
	int			y;
	int			width;
	int			height;
	tcu::RGBA	color;
};

struct ApiFunctions
{
	glw::Functions	gl;
};

static ClearOp computeRandomClear (de::Random& rnd, int width, int height)
{
	int			w		= rnd.getInt(1, width);
	int			h		= rnd.getInt(1, height);
	int			x		= rnd.getInt(0, width-w);
	int			y		= rnd.getInt(0, height-h);
	tcu::RGBA	col		(rnd.getUint32());

	return ClearOp(x, y, w, h, col);
}

static void renderReference (tcu::Surface& dst, const vector<ClearOp>& clears, const tcu::PixelFormat& pixelFormat)
{
	for (vector<ClearOp>::const_iterator clearIter = clears.begin(); clearIter != clears.end(); clearIter++)
	{
		tcu::PixelBufferAccess access = tcu::getSubregion(dst.getAccess(), clearIter->x, clearIter->y, 0, clearIter->width, clearIter->height, 1);
		tcu::clear(access, pixelFormat.convertColor(clearIter->color).toIVec());
	}
}

static void renderClear (EGLint api, const ApiFunctions& func, const ClearOp& clear)
{
	switch (api)
	{
		case EGL_OPENGL_ES_BIT:			gles1::clear(clear.x, clear.y, clear.width, clear.height, clear.color.toVec());				break;
		case EGL_OPENGL_ES2_BIT:		gles2::clear(func.gl, clear.x, clear.y, clear.width, clear.height, clear.color.toVec());	break;
		case EGL_OPENGL_ES3_BIT_KHR:	gles2::clear(func.gl, clear.x, clear.y, clear.width, clear.height, clear.color.toVec());	break;
		case EGL_OPENVG_BIT:			vg::clear	(clear.x, clear.y, clear.width, clear.height, clear.color.toVec());				break;
		default:
			DE_ASSERT(DE_FALSE);
	}
}

static void finish (EGLint api, const ApiFunctions& func)
{
	switch (api)
	{
		case EGL_OPENGL_ES_BIT:			gles1::finish();		break;
		case EGL_OPENGL_ES2_BIT:		gles2::finish(func.gl);	break;
		case EGL_OPENGL_ES3_BIT_KHR:	gles2::finish(func.gl);	break;
		case EGL_OPENVG_BIT:			vg::finish();			break;
		default:
			DE_ASSERT(DE_FALSE);
	}
}

static void readPixels (EGLint api, const ApiFunctions& func, tcu::Surface& dst)
{
	switch (api)
	{
		case EGL_OPENGL_ES_BIT:			gles1::readPixels	(dst, 0, 0, dst.getWidth(), dst.getHeight());			break;
		case EGL_OPENGL_ES2_BIT:		gles2::readPixels	(func.gl, dst, 0, 0, dst.getWidth(), dst.getHeight());	break;
		case EGL_OPENGL_ES3_BIT_KHR:	gles2::readPixels	(func.gl, dst, 0, 0, dst.getWidth(), dst.getHeight());	break;
		case EGL_OPENVG_BIT:			vg::readPixels		(dst, 0, 0, dst.getWidth(), dst.getHeight());			break;
		default:
			DE_ASSERT(DE_FALSE);
	}
}

static tcu::PixelFormat getPixelFormat (const Library& egl, EGLDisplay display, EGLConfig config)
{
	tcu::PixelFormat pixelFmt;

	egl.getConfigAttrib(display, config, EGL_RED_SIZE,		&pixelFmt.redBits);
	egl.getConfigAttrib(display, config, EGL_GREEN_SIZE,	&pixelFmt.greenBits);
	egl.getConfigAttrib(display, config, EGL_BLUE_SIZE,		&pixelFmt.blueBits);
	egl.getConfigAttrib(display, config, EGL_ALPHA_SIZE,	&pixelFmt.alphaBits);

	return pixelFmt;
}

// SingleThreadColorClearCase

SingleThreadColorClearCase::SingleThreadColorClearCase (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 SingleThreadColorClearCase::executeForContexts (EGLDisplay display, EGLSurface surface, const Config& config, const std::vector<std::pair<EGLint, EGLContext> >& contexts)
{
	const Library&		egl			= m_eglTestCtx.getLibrary();

	const tcu::IVec2	surfaceSize	= eglu::getSurfaceSize(egl, display, surface);
	const int			width		= surfaceSize.x();
	const int			height		= surfaceSize.y();

	TestLog&			log			= m_testCtx.getLog();

	tcu::Surface		refFrame	(width, height);
	tcu::Surface		frame		(width, height);
	tcu::PixelFormat	pixelFmt	= getPixelFormat(egl, display, config.config);

	de::Random			rnd			(deStringHash(getName()));
	vector<ClearOp>		clears;
	const int			ctxClears	= 2;
	const int			numIters	= 3;

	ApiFunctions		funcs;

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

	// Clear to black using first context.
	{
		EGLint		api			= contexts[0].first;
		EGLContext	context		= contexts[0].second;
		ClearOp		clear		(0, 0, width, height, RGBA::black());

		egl.makeCurrent(display, surface, surface, context);
		EGLU_CHECK_MSG(egl, "eglMakeCurrent");

		renderClear(api, funcs, clear);
		finish(api, funcs);
		clears.push_back(clear);
	}

	// Render.
	for (int iterNdx = 0; iterNdx < numIters; iterNdx++)
	{
		for (vector<std::pair<EGLint, EGLContext> >::const_iterator ctxIter = contexts.begin(); ctxIter != contexts.end(); ctxIter++)
		{
			EGLint		api			= ctxIter->first;
			EGLContext	context		= ctxIter->second;

			egl.makeCurrent(display, surface, surface, context);
			EGLU_CHECK_MSG(egl, "eglMakeCurrent");

			for (int clearNdx = 0; clearNdx < ctxClears; clearNdx++)
			{
				ClearOp clear = computeRandomClear(rnd, width, height);

				renderClear(api, funcs, clear);
				clears.push_back(clear);
			}

			finish(api, funcs);
		}
	}

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

		egl.makeCurrent(display, surface, surface, context);
		EGLU_CHECK_MSG(egl, "eglMakeCurrent");

		readPixels(api, funcs, frame);
	}

	egl.makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
	EGLU_CHECK_MSG(egl, "eglMakeCurrent");

	// Render reference.
	renderReference(refFrame, clears, pixelFmt);

	// Compare images
	{
		bool imagesOk = tcu::pixelThresholdCompare(log, "ComparisonResult", "Image comparison result", refFrame, frame, RGBA(1,1,1,1) + pixelFmt.getColorThreshold(), tcu::COMPARE_LOG_RESULT);

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

// MultiThreadColorClearCase

enum
{
	NUM_CLEARS_PER_PACKET	= 2 //!< Number of clears performed in one context activation in one thread.
};

class ColorClearThread;

typedef de::SharedPtr<ColorClearThread>	ColorClearThreadSp;
typedef de::SharedPtr<de::Semaphore>	SemaphoreSp;

struct ClearPacket
{
	ClearPacket (void)
	{
	}

	ClearOp			clears[NUM_CLEARS_PER_PACKET];
	SemaphoreSp		wait;
	SemaphoreSp		signal;
};

class ColorClearThread : public de::Thread
{
public:
	ColorClearThread (const Library& egl, EGLDisplay display, EGLSurface surface, EGLContext context, EGLint api, const ApiFunctions& funcs, const std::vector<ClearPacket>& packets)
		: m_egl		(egl)
		, m_display	(display)
		, m_surface	(surface)
		, m_context	(context)
		, m_api		(api)
		, m_funcs	(funcs)
		, m_packets	(packets)
	{
	}

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

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

			// Execute clears.
			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(packetIter->clears); ndx++)
				renderClear(m_api, m_funcs, packetIter->clears[ndx]);

			finish(m_api, m_funcs);
			// Release context.
			m_egl.makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

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

private:
	const Library&					m_egl;
	EGLDisplay						m_display;
	EGLSurface						m_surface;
	EGLContext						m_context;
	EGLint							m_api;
	const ApiFunctions&				m_funcs;
	const std::vector<ClearPacket>&	m_packets;
};

MultiThreadColorClearCase::MultiThreadColorClearCase (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 MultiThreadColorClearCase::executeForContexts (EGLDisplay display, EGLSurface surface, const Config& config, const std::vector<std::pair<EGLint, EGLContext> >& contexts)
{
	const Library&		egl			= m_eglTestCtx.getLibrary();

	const tcu::IVec2	surfaceSize	= eglu::getSurfaceSize(egl, display, surface);
	const int			width		= surfaceSize.x();
	const int			height		= surfaceSize.y();

	TestLog&			log			= m_testCtx.getLog();

	tcu::Surface		refFrame	(width, height);
	tcu::Surface		frame		(width, height);
	tcu::PixelFormat	pixelFmt	= getPixelFormat(egl, display, config.config);

	de::Random			rnd			(deStringHash(getName()));

	ApiFunctions		funcs;

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

	// Create clear packets.
	const int						numPacketsPerThread		= 2;
	int								numThreads				= (int)contexts.size();
	int								numPackets				= numThreads * numPacketsPerThread;

	vector<SemaphoreSp>				semaphores				(numPackets+1);
	vector<vector<ClearPacket> >	packets					(numThreads);
	vector<ColorClearThreadSp>		threads					(numThreads);

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

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

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

			// Threads take turns with packets.
			packet.wait		= semaphores[packetNdx*numThreads + threadNdx];
			packet.signal	= semaphores[packetNdx*numThreads + threadNdx + 1];

			for (int clearNdx = 0; clearNdx < DE_LENGTH_OF_ARRAY(packet.clears); clearNdx++)
			{
				// First clear is always full-screen black.
				if (threadNdx == 0 && packetNdx == 0 && clearNdx == 0)
					packet.clears[clearNdx] = ClearOp(0, 0, width, height, RGBA::black());
				else
					packet.clears[clearNdx] = computeRandomClear(rnd, width, height);
			}
		}
	}

	// Create and launch threads (actual rendering starts once first semaphore is signaled).
	for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
	{
		threads[threadNdx] = ColorClearThreadSp(new ColorClearThread(egl, display, surface, contexts[threadNdx].second, contexts[threadNdx].first, funcs, 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;

		egl.makeCurrent(display, surface, surface, context);
		EGLU_CHECK_MSG(egl, "eglMakeCurrent");

		readPixels(api, funcs, frame);
	}

	egl.makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
	EGLU_CHECK_MSG(egl, "eglMakeCurrent");

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

	// Render reference.
	for (int packetNdx = 0; packetNdx < numPacketsPerThread; packetNdx++)
	{
		for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
		{
			const ClearPacket& packet = packets[threadNdx][packetNdx];
			for (int clearNdx = 0; clearNdx < DE_LENGTH_OF_ARRAY(packet.clears); clearNdx++)
			{
				tcu::PixelBufferAccess access = tcu::getSubregion(refFrame.getAccess(),
																  packet.clears[clearNdx].x, packet.clears[clearNdx].y, 0,
																  packet.clears[clearNdx].width, packet.clears[clearNdx].height, 1);
				tcu::clear(access, pixelFmt.convertColor(packet.clears[clearNdx].color).toIVec());
			}
		}
	}

	// Compare images
	{
		bool imagesOk = tcu::pixelThresholdCompare(log, "ComparisonResult", "Image comparison result", refFrame, frame, RGBA(1,1,1,1) + pixelFmt.getColorThreshold(), tcu::COMPARE_LOG_RESULT);

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

} // egl
} // deqp
