/*-------------------------------------------------------------------------
 * 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 "deSharedPtr.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, const glu::RenderContext* sharedContext = DE_NULL);
	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, const glu::RenderContext* sharedContext);
	void								destroy					(void);

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

	de::SharedPtr<NativeDisplay>		m_display;
	NativeWindow*						m_window;
	NativePixmap*						m_pixmap;

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

	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, const glu::RenderContext* sharedContext)
	: 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_eglSharedContext	(EGL_NO_CONTEXT)

	, m_dynamicGLLibrary	(DE_NULL)
{
	DE_ASSERT(displayFactory);

	try
	{
		create(displayFactory, windowFactory, pixmapFactory, config, sharedContext);
	}
	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_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, const glu::RenderContext *sharedContext)
{
	glu::RenderConfig::SurfaceType	surfaceType	= config.surfaceType;

	DE_ASSERT(displayFactory);

	if (DE_NULL == sharedContext)
		m_display = de::SharedPtr<NativeDisplay>(displayFactory->createDisplay());
	else
	{
		const RenderContext* context = dynamic_cast<const RenderContext*>(sharedContext);
		m_eglSharedContext			 = context->m_eglContext;
		m_display					 = context->m_display;
	}

	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.get(), 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.get(), 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, m_eglSharedContext, 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);
	}

	egl.swapInterval(m_eglDisplay, 0);
}

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

		if (m_eglSharedContext == EGL_NO_CONTEXT)
			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_dynamicGLLibrary;

	m_window			= DE_NULL;
	m_pixmap			= 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.get(), 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 glu::RenderContext *sharedContext) 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, sharedContext);
}

} // eglu
