/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * 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 GL context factory using EGL.
 *//*--------------------------------------------------------------------*/

#include "egluGLContextFactory.hpp"

#include "tcuRenderTarget.hpp"
#include "tcuPlatform.hpp"
#include "tcuCommandLine.hpp"

#include "gluDefs.hpp"

#include "egluDefs.hpp"
#include "egluUtil.hpp"
#include "egluGLUtil.hpp"
#include "egluNativeWindow.hpp"
#include "egluNativePixmap.hpp"
#include "egluStrUtil.hpp"

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

#include "glwInitFunctions.hpp"
#include "glwInitES20Direct.hpp"
#include "glwInitES30Direct.hpp"
#include "glwInitES31Direct.hpp"
#include "glwInitES32Direct.hpp"

#include "deDynamicLibrary.hpp"
#include "deSTLUtil.hpp"

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

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

// \todo [2014-03-12 pyry] Use command line arguments for libraries?

// Default library names
#if !defined(DEQP_GLES2_LIBRARY_PATH)
#	if (DE_OS == DE_OS_WIN32)
#		define DEQP_GLES2_LIBRARY_PATH "libGLESv2.dll"
#	else
#		define DEQP_GLES2_LIBRARY_PATH "libGLESv2.so"
#	endif
#endif

#if !defined(DEQP_GLES3_LIBRARY_PATH)
#	define DEQP_GLES3_LIBRARY_PATH DEQP_GLES2_LIBRARY_PATH
#endif

#if !defined(DEQP_OPENGL_LIBRARY_PATH)
#	if (DE_OS == DE_OS_WIN32)
#		define DEQP_OPENGL_LIBRARY_PATH "opengl32.dll"
#	else
#		define DEQP_OPENGL_LIBRARY_PATH "libGL.so"
#	endif
#endif

namespace eglu
{

using namespace eglw;

namespace
{

enum
{
	DEFAULT_OFFSCREEN_WIDTH		= 512,
	DEFAULT_OFFSCREEN_HEIGHT	= 512
};

class GetProcFuncLoader : public glw::FunctionLoader
{
public:
	GetProcFuncLoader (const Library& egl)
		: m_egl(egl)
	{
	}

	glw::GenericFuncType get (const char* name) const
	{
		return (glw::GenericFuncType)m_egl.getProcAddress(name);
	}

protected:
	const Library& m_egl;
};

class DynamicFuncLoader : public glw::FunctionLoader
{
public:
	DynamicFuncLoader	(de::DynamicLibrary* library)
		: m_library(library)
	{
	}

	glw::GenericFuncType get (const char* name) const
	{
		return (glw::GenericFuncType)m_library->getFunction(name);
	}

private:
	de::DynamicLibrary*	m_library;
};

class RenderContext : public GLRenderContext
{
public:
										RenderContext			(const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config);
	virtual								~RenderContext			(void);

	virtual glu::ContextType			getType					(void) const { return m_renderConfig.type;		}
	virtual const glw::Functions&		getFunctions			(void) const { return m_glFunctions;			}
	virtual const tcu::RenderTarget&	getRenderTarget			(void) const { return m_glRenderTarget;			}
	virtual void						postIterate				(void);

	virtual EGLDisplay					getEGLDisplay			(void) const { return m_eglDisplay;				}
	virtual EGLContext					getEGLContext			(void) const { return m_eglContext;				}
	virtual EGLConfig					getEGLConfig			(void) const { return m_eglConfig;				}
	virtual const eglw::Library&		getLibrary				(void) const { return m_display->getLibrary();	}

	virtual eglw::GenericFuncType		getProcAddress			(const char* name) const;

	virtual void						makeCurrent				(void);

private:
	void								create					(const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config);
	void								destroy					(void);

	const glu::RenderConfig				m_renderConfig;
	const NativeWindowFactory* const	m_nativeWindowFactory;	// Stored in case window must be re-created

	NativeDisplay*						m_display;
	NativeWindow*						m_window;
	NativePixmap*						m_pixmap;

	EGLDisplay							m_eglDisplay;
	EGLConfig							m_eglConfig;
	EGLSurface							m_eglSurface;
	EGLContext							m_eglContext;

	tcu::RenderTarget					m_glRenderTarget;
	de::DynamicLibrary*					m_dynamicGLLibrary;
	glw::Functions						m_glFunctions;
};

RenderContext::RenderContext (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config)
	: m_renderConfig		(config)
	, m_nativeWindowFactory	(windowFactory)
	, m_display				(DE_NULL)
	, m_window				(DE_NULL)
	, m_pixmap				(DE_NULL)

	, m_eglDisplay			(EGL_NO_DISPLAY)
	, m_eglSurface			(EGL_NO_SURFACE)
	, m_eglContext			(EGL_NO_CONTEXT)

	, m_dynamicGLLibrary	(DE_NULL)
{
	DE_ASSERT(displayFactory);

	try
	{
		create(displayFactory, windowFactory, pixmapFactory, config);
	}
	catch (...)
	{
		destroy();
		throw;
	}
}

RenderContext::~RenderContext(void)
{
	try
	{
		destroy();
	}
	catch (...)
	{
		// destroy() calls EGL functions that are checked and may throw exceptions
	}

	delete m_window;
	delete m_pixmap;
	delete m_display;
	delete m_dynamicGLLibrary;
}

static WindowParams::Visibility getNativeWindowVisibility (glu::RenderConfig::Visibility visibility)
{
	using glu::RenderConfig;

	switch (visibility)
	{
		case RenderConfig::VISIBILITY_HIDDEN:		return WindowParams::VISIBILITY_HIDDEN;
		case RenderConfig::VISIBILITY_VISIBLE:		return WindowParams::VISIBILITY_VISIBLE;
		case RenderConfig::VISIBILITY_FULLSCREEN:	return WindowParams::VISIBILITY_FULLSCREEN;
		default:
			DE_ASSERT((int)visibility == RenderConfig::DONT_CARE);
			return WindowParams::VISIBILITY_DONT_CARE;
	}
}

typedef std::pair<NativeWindow*, EGLSurface> WindowSurfacePair;
typedef std::pair<NativePixmap*, EGLSurface> PixmapSurfacePair;

WindowSurfacePair createWindow (NativeDisplay* nativeDisplay, const NativeWindowFactory* windowFactory, EGLDisplay eglDisplay, EGLConfig eglConfig, const glu::RenderConfig& config)
{
	const int						width			= (config.width		== glu::RenderConfig::DONT_CARE ? WindowParams::SIZE_DONT_CARE	: config.width);
	const int						height			= (config.height	== glu::RenderConfig::DONT_CARE ? WindowParams::SIZE_DONT_CARE	: config.height);
	const WindowParams::Visibility	visibility		= getNativeWindowVisibility(config.windowVisibility);
	NativeWindow*					nativeWindow	= DE_NULL;
	EGLSurface						surface			= EGL_NO_SURFACE;
	const EGLAttrib					attribList[]	= { EGL_NONE };

	nativeWindow = windowFactory->createWindow(nativeDisplay, eglDisplay, eglConfig, &attribList[0], WindowParams(width, height, visibility));

	try
	{
		surface = eglu::createWindowSurface(*nativeDisplay, *nativeWindow, eglDisplay, eglConfig, attribList);
	}
	catch (...)
	{
		delete nativeWindow;
		throw;
	}

	return WindowSurfacePair(nativeWindow, surface);
}

PixmapSurfacePair createPixmap (NativeDisplay* nativeDisplay, const NativePixmapFactory* pixmapFactory, EGLDisplay eglDisplay, EGLConfig eglConfig, const glu::RenderConfig& config)
{
	const int			width			= (config.width		== glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_WIDTH	: config.width);
	const int			height			= (config.height	== glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_HEIGHT	: config.height);
	NativePixmap*		nativePixmap	= DE_NULL;
	EGLSurface			surface			= EGL_NO_SURFACE;
	const EGLAttrib		attribList[]	= { EGL_NONE };

	nativePixmap = pixmapFactory->createPixmap(nativeDisplay, eglDisplay, eglConfig, &attribList[0], width, height);

	try
	{
		surface = eglu::createPixmapSurface(*nativeDisplay, *nativePixmap, eglDisplay, eglConfig, attribList);
	}
	catch (...)
	{
		delete nativePixmap;
		throw;
	}

	return PixmapSurfacePair(nativePixmap, surface);
}

EGLSurface createPBuffer (const Library& egl, EGLDisplay display, EGLConfig eglConfig, const glu::RenderConfig& config)
{
	const int		width			= (config.width		== glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_WIDTH	: config.width);
	const int		height			= (config.height	== glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_HEIGHT	: config.height);
	EGLSurface		surface;
	const EGLint	attribList[]	=
	{
		EGL_WIDTH,	width,
		EGL_HEIGHT,	height,
		EGL_NONE
	};

	surface = egl.createPbufferSurface(display, eglConfig, &(attribList[0]));
	EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()");

	return surface;
}

void RenderContext::makeCurrent (void)
{
	const Library& egl = m_display->getLibrary();

	EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
}

glw::GenericFuncType RenderContext::getProcAddress (const char* name) const
{
	return (glw::GenericFuncType)m_display->getLibrary().getProcAddress(name);
}

void RenderContext::create (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config)
{
	glu::RenderConfig::SurfaceType	surfaceType	= config.surfaceType;

	DE_ASSERT(displayFactory);

	m_display		= displayFactory->createDisplay();
	m_eglDisplay	= eglu::getDisplay(*m_display);

	const Library& egl = m_display->getLibrary();

	{
		EGLint major = 0;
		EGLint minor = 0;
		EGLU_CHECK_CALL(egl, initialize(m_eglDisplay, &major, &minor));
	}

	m_eglConfig	= chooseConfig(egl, m_eglDisplay, config);

	if (surfaceType == glu::RenderConfig::SURFACETYPE_DONT_CARE)
	{
		// Choose based on what selected configuration supports
		const EGLint supportedTypes = eglu::getConfigAttribInt(egl, m_eglDisplay, m_eglConfig, EGL_SURFACE_TYPE);

		if ((supportedTypes & EGL_WINDOW_BIT) != 0)
			surfaceType = glu::RenderConfig::SURFACETYPE_WINDOW;
		else if ((supportedTypes & EGL_PBUFFER_BIT) != 0)
			surfaceType = glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC;
		else if ((supportedTypes & EGL_PIXMAP_BIT) != 0)
			surfaceType = glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE;
		else
			throw tcu::NotSupportedError("Selected EGL config doesn't support any surface types", DE_NULL, __FILE__, __LINE__);
	}

	switch (surfaceType)
	{
		case glu::RenderConfig::SURFACETYPE_WINDOW:
		{
			if (windowFactory)
			{
				const WindowSurfacePair windowSurface = createWindow(m_display, windowFactory, m_eglDisplay, m_eglConfig, config);
				m_window		= windowSurface.first;
				m_eglSurface	= windowSurface.second;
			}
			else
				throw tcu::NotSupportedError("EGL platform doesn't support windows", DE_NULL, __FILE__, __LINE__);
			break;
		}

		case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:
		{
			if (pixmapFactory)
			{
				const PixmapSurfacePair pixmapSurface = createPixmap(m_display, pixmapFactory, m_eglDisplay, m_eglConfig, config);
				m_pixmap		= pixmapSurface.first;
				m_eglSurface	= pixmapSurface.second;
			}
			else
				throw tcu::NotSupportedError("EGL platform doesn't support pixmaps", DE_NULL, __FILE__, __LINE__);
			break;
		}

		case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:
			m_eglSurface = createPBuffer(egl, m_eglDisplay, m_eglConfig, config);
			break;

		default:
			throw tcu::InternalError("Invalid surface type");
	}

	m_eglContext = createGLContext(egl, m_eglDisplay, m_eglConfig, config.type, config.resetNotificationStrategy);

	EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));

	// Init core functions

	if (hasExtension(egl, m_eglDisplay, "EGL_KHR_get_all_proc_addresses"))
	{
		// Use eglGetProcAddress() for core functions
		GetProcFuncLoader funcLoader(egl);
		glu::initCoreFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
	}
#if defined(DEQP_GLES2_DIRECT_LINK)
	else if (config.type.getAPI() == glu::ApiType::es(2,0))
	{
		glw::initES20Direct(&m_glFunctions);
	}
#endif
#if defined(DEQP_GLES3_DIRECT_LINK)
	else if (config.type.getAPI() == glu::ApiType::es(3,0))
	{
		glw::initES30Direct(&m_glFunctions);
	}
#endif
#if defined(DEQP_GLES31_DIRECT_LINK)
	else if (config.type.getAPI() == glu::ApiType::es(3,1))
	{
		glw::initES31Direct(&m_glFunctions);
	}
#endif
#if defined(DEQP_GLES32_DIRECT_LINK)
	else if (config.type.getAPI() == glu::ApiType::es(3,2))
	{
		glw::initES32Direct(&m_glFunctions);
	}
#endif
	else
	{
		const char* libraryPath = DE_NULL;

		if (glu::isContextTypeES(config.type))
		{
			if (config.type.getMinorVersion() <= 2)
				libraryPath = DEQP_GLES2_LIBRARY_PATH;
			else
				libraryPath = DEQP_GLES3_LIBRARY_PATH;
		}
		else
			libraryPath = DEQP_OPENGL_LIBRARY_PATH;

		m_dynamicGLLibrary = new de::DynamicLibrary(libraryPath);

		DynamicFuncLoader funcLoader(m_dynamicGLLibrary);
		glu::initCoreFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
	}

	// Init extension functions
	{
		GetProcFuncLoader extLoader(egl);
		glu::initExtensionFunctions(&m_glFunctions, &extLoader, config.type.getAPI());
	}

	{
		EGLint				width, height, depthBits, stencilBits, numSamples;
		tcu::PixelFormat	pixelFmt;

		egl.querySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH,		&width);
		egl.querySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT,	&height);

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

		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_DEPTH_SIZE,		&depthBits);
		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_STENCIL_SIZE,	&stencilBits);
		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_SAMPLES,			&numSamples);

		EGLU_CHECK_MSG(egl, "Failed to query config attributes");

		m_glRenderTarget = tcu::RenderTarget(width, height, pixelFmt, depthBits, stencilBits, numSamples);
	}
}

void RenderContext::destroy (void)
{
	if (m_eglDisplay != EGL_NO_DISPLAY)
	{
		const Library& egl = m_display->getLibrary();

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

		if (m_eglSurface != EGL_NO_SURFACE)
			EGLU_CHECK_CALL(egl, destroySurface(m_eglDisplay, m_eglSurface));

		if (m_eglContext != EGL_NO_CONTEXT)
			EGLU_CHECK_CALL(egl, destroyContext(m_eglDisplay, m_eglContext));

		EGLU_CHECK_CALL(egl, terminate(m_eglDisplay));

		m_eglDisplay	= EGL_NO_DISPLAY;
		m_eglSurface	= EGL_NO_SURFACE;
		m_eglContext	= EGL_NO_CONTEXT;
	}

	delete m_window;
	delete m_pixmap;
	delete m_display;
	delete m_dynamicGLLibrary;

	m_window			= DE_NULL;
	m_pixmap			= DE_NULL;
	m_display			= DE_NULL;
	m_dynamicGLLibrary	= DE_NULL;
}

void RenderContext::postIterate (void)
{
	const Library& egl = m_display->getLibrary();

	if (m_window)
	{
		EGLBoolean	swapOk		= egl.swapBuffers(m_eglDisplay, m_eglSurface);
		EGLint		error		= egl.getError();
		const bool	badWindow	= error == EGL_BAD_SURFACE || error == EGL_BAD_NATIVE_WINDOW;

		if (!swapOk && !badWindow)
			throw tcu::ResourceError(string("eglSwapBuffers() failed: ") + getErrorStr(error).toString());

		try
		{
			m_window->processEvents();
		}
		catch (const WindowDestroyedError&)
		{
			tcu::print("Warning: Window destroyed, recreating...\n");

			EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
			EGLU_CHECK_CALL(egl, destroySurface(m_eglDisplay, m_eglSurface));
			m_eglSurface = EGL_NO_SURFACE;

			delete m_window;
			m_window = DE_NULL;

			try
			{
				WindowSurfacePair windowSurface = createWindow(m_display, m_nativeWindowFactory, m_eglDisplay, m_eglConfig, m_renderConfig);
				m_window		= windowSurface.first;
				m_eglSurface	= windowSurface.second;

				EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));

				swapOk	= EGL_TRUE;
				error	= EGL_SUCCESS;
			}
			catch (const std::exception& e)
			{
				if (m_eglSurface)
				{
					egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
					egl.destroySurface(m_eglDisplay, m_eglSurface);
					m_eglSurface = EGL_NO_SURFACE;
				}

				delete m_window;
				m_window = DE_NULL;

				throw tcu::ResourceError(string("Failed to re-create window: ") + e.what());
			}
		}

		if (!swapOk)
		{
			DE_ASSERT(badWindow);
			throw tcu::ResourceError(string("eglSwapBuffers() failed: ") + getErrorStr(error).toString());
		}

		// Refresh dimensions
		{
			int	newWidth	= 0;
			int	newHeight	= 0;

			egl.querySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH,		&newWidth);
			egl.querySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT,	&newHeight);
			EGLU_CHECK_MSG(egl, "Failed to query window size");

			if (newWidth	!= m_glRenderTarget.getWidth() ||
				newHeight	!= m_glRenderTarget.getHeight())
			{
				tcu::print("Warning: Window size changed (%dx%d -> %dx%d), test results might be invalid!\n",
						   m_glRenderTarget.getWidth(), m_glRenderTarget.getHeight(), newWidth, newHeight);

				m_glRenderTarget = tcu::RenderTarget(newWidth, newHeight,
													 m_glRenderTarget.getPixelFormat(),
													 m_glRenderTarget.getDepthBits(),
													 m_glRenderTarget.getStencilBits(),
													 m_glRenderTarget.getNumSamples());
			}
		}
	}
	else
		m_glFunctions.flush();
}

} // anonymous

GLContextFactory::GLContextFactory (const NativeDisplayFactoryRegistry& displayFactoryRegistry)
	: glu::ContextFactory		("egl", "EGL OpenGL Context")
	, m_displayFactoryRegistry	(displayFactoryRegistry)
{
}

glu::RenderContext* GLContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine) const
{
	const NativeDisplayFactory& displayFactory = selectNativeDisplayFactory(m_displayFactoryRegistry, cmdLine);

	const NativeWindowFactory*	windowFactory;
	const NativePixmapFactory*	pixmapFactory;

	try
	{
		windowFactory = &selectNativeWindowFactory(displayFactory, cmdLine);
	}
	catch (const tcu::NotSupportedError&)
	{
		windowFactory = DE_NULL;
	}

	try
	{
		pixmapFactory = &selectNativePixmapFactory(displayFactory, cmdLine);
	}
	catch (const tcu::NotSupportedError&)
	{
		pixmapFactory = DE_NULL;
	}

	return new RenderContext(&displayFactory, windowFactory, pixmapFactory, config);
}

} // eglu
