/*-------------------------------------------------------------------------
 * 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 EGL utilities
 *//*--------------------------------------------------------------------*/

#include "egluUtil.hpp"
#include "egluDefs.hpp"
#include "egluNativeDisplay.hpp"
#include "egluConfigFilter.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"
#include "tcuCommandLine.hpp"
#include "deSTLUtil.hpp"
#include "deStringUtil.hpp"
#include "glwEnums.hpp"

#include <algorithm>
#include <sstream>

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

namespace eglu
{

using namespace eglw;

vector<EGLint> attribMapToList (const AttribMap& attribs)
{
	vector<EGLint> attribList;

	for (AttribMap::const_iterator it = attribs.begin(); it != attribs.end(); ++it)
	{
		attribList.push_back(it->first);
		attribList.push_back(it->second);
	}

	attribList.push_back(EGL_NONE);

	return attribList;
}

Version getVersion (const Library& egl, EGLDisplay display)
{
	EGLint major, minor;

	// eglInitialize on already initialized displays just returns the version.
	EGLU_CHECK_CALL(egl, initialize(display, &major, &minor));

	return Version(major, minor);
}

vector<string> getExtensions (const Library& egl, EGLDisplay display)
{
	const char*	const extensionStr = egl.queryString(display, EGL_EXTENSIONS);

	EGLU_CHECK_MSG(egl, "Querying extensions failed");

	return de::splitString(extensionStr, ' ');
}

bool hasExtension (const Library& egl, EGLDisplay display, const string& str)
{
	const vector<string> extensions = getExtensions(egl, display);
	return de::contains(extensions.begin(), extensions.end(), str);
}

vector<string> getClientExtensions (const Library& egl)
{
	const char*	const extensionStr = egl.queryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
	const EGLint		eglError			= egl.getError();
	if (eglError == EGL_BAD_DISPLAY && extensionStr == DE_NULL) {
		// We do not support client extensions
		TCU_THROW(NotSupportedError, "EGL_EXT_client_extensions not supported");
	}

	EGLU_CHECK_MSG(egl, "Querying extensions failed");

	return de::splitString(extensionStr, ' ');
}

vector<string> getDisplayExtensions (const Library& egl, EGLDisplay display)
{
	DE_ASSERT(display != EGL_NO_DISPLAY);

	return getExtensions(egl, display);
}

vector<EGLConfig> getConfigs (const Library& egl, EGLDisplay display)
{
	vector<EGLConfig>	configs;
	EGLint				configCount	= 0;
	EGLU_CHECK_CALL(egl, getConfigs(display, DE_NULL, 0, &configCount));

	if (configCount > 0)
	{
		configs.resize(configCount);
		EGLU_CHECK_CALL(egl, getConfigs(display, &(configs[0]), (EGLint)configs.size(), &configCount));
	}

	return configs;
}

vector<EGLConfig> chooseConfigs (const Library& egl, EGLDisplay display, const EGLint* attribList)
{
	EGLint	numConfigs	= 0;

	EGLU_CHECK_CALL(egl, chooseConfig(display, attribList, DE_NULL, 0, &numConfigs));

	{
		vector<EGLConfig> configs(numConfigs);

		if (numConfigs > 0)
			EGLU_CHECK_CALL(egl, chooseConfig(display, attribList, &configs.front(), numConfigs, &numConfigs));

		return configs;
	}
}

vector<EGLConfig> chooseConfigs (const Library& egl, EGLDisplay display, const FilterList& filters)
{
	const vector<EGLConfig>	allConfigs		(getConfigs(egl, display));
	vector<EGLConfig>		matchingConfigs;

	for (vector<EGLConfig>::const_iterator cfg = allConfigs.begin(); cfg != allConfigs.end(); ++cfg)
	{
		if (filters.match(egl, display, *cfg))
			matchingConfigs.push_back(*cfg);
	}

	return matchingConfigs;
}

EGLConfig chooseSingleConfig (const Library& egl, EGLDisplay display, const FilterList& filters)
{
	const vector<EGLConfig>	allConfigs	(getConfigs(egl, display));

	for (vector<EGLConfig>::const_iterator cfg = allConfigs.begin(); cfg != allConfigs.end(); ++cfg)
	{
		if (filters.match(egl, display, *cfg))
			return *cfg;
	}

	TCU_THROW(NotSupportedError, "No matching EGL config found");
}

EGLConfig chooseSingleConfig (const Library& egl, EGLDisplay display, const EGLint* attribList)
{
	const vector<EGLConfig> configs (chooseConfigs(egl, display, attribList));
	if (configs.empty())
		TCU_THROW(NotSupportedError, "No matching EGL config found");

	return configs.front();
}

vector<EGLConfig> chooseConfigs (const Library& egl, EGLDisplay display, const AttribMap& attribs)
{
	const vector<EGLint>	attribList	= attribMapToList(attribs);
	return chooseConfigs(egl, display, &attribList.front());
}

EGLConfig chooseSingleConfig (const Library& egl, EGLDisplay display, const AttribMap& attribs)
{
	const vector<EGLint>	attribList	= attribMapToList(attribs);
	return chooseSingleConfig(egl, display, &attribList.front());
}

EGLConfig chooseConfigByID (const Library& egl, EGLDisplay display, EGLint id)
{
	AttribMap attribs;

	attribs[EGL_CONFIG_ID]			= id;
	attribs[EGL_TRANSPARENT_TYPE]	= EGL_DONT_CARE;
	attribs[EGL_COLOR_BUFFER_TYPE]	= EGL_DONT_CARE;
	attribs[EGL_RENDERABLE_TYPE]	= EGL_DONT_CARE;
	attribs[EGL_SURFACE_TYPE]		= EGL_DONT_CARE;

	return chooseSingleConfig(egl, display, attribs);
}

EGLint getConfigAttribInt (const Library& egl, EGLDisplay display, EGLConfig config, EGLint attrib)
{
	EGLint value = 0;
	EGLU_CHECK_CALL(egl, getConfigAttrib(display, config, attrib, &value));
	return value;
}

EGLint getConfigID (const Library& egl, EGLDisplay display, EGLConfig config)
{
	return getConfigAttribInt(egl, display, config, EGL_CONFIG_ID);
}

EGLint querySurfaceInt (const Library& egl, EGLDisplay display, EGLSurface surface, EGLint attrib)
{
	EGLint value = 0;
	EGLU_CHECK_CALL(egl, querySurface(display, surface, attrib, &value));
	return value;
}

tcu::IVec2 getSurfaceSize (const Library& egl, EGLDisplay display, EGLSurface surface)
{
	const EGLint width	= querySurfaceInt(egl, display, surface, EGL_WIDTH);
	const EGLint height	= querySurfaceInt(egl, display, surface, EGL_HEIGHT);
	return tcu::IVec2(width, height);
}

tcu::IVec2 getSurfaceResolution (const Library& egl, EGLDisplay display, EGLSurface surface)
{
	const EGLint hRes	= querySurfaceInt(egl, display, surface, EGL_HORIZONTAL_RESOLUTION);
	const EGLint vRes	= querySurfaceInt(egl, display, surface, EGL_VERTICAL_RESOLUTION);

	if (hRes == EGL_UNKNOWN || vRes == EGL_UNKNOWN)
		TCU_THROW(NotSupportedError, "Surface doesn't support pixel density queries");
	return tcu::IVec2(hRes, vRes);
}

//! Get EGLdisplay using eglGetDisplay() or eglGetPlatformDisplayEXT()
EGLDisplay getDisplay (NativeDisplay& nativeDisplay)
{
	const Library&	egl								= nativeDisplay.getLibrary();
	const bool		supportsLegacyGetDisplay		= (nativeDisplay.getCapabilities() & NativeDisplay::CAPABILITY_GET_DISPLAY_LEGACY) != 0;
	bool			maySupportPlatformGetDisplay	= (nativeDisplay.getCapabilities() & NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM) != 0;
	bool			maySupportPlatformGetDisplayEXT	= (nativeDisplay.getCapabilities() & NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM_EXT) != 0;
	bool			usePlatformExt					= false;
	EGLDisplay		display							= EGL_NO_DISPLAY;

	TCU_CHECK_INTERNAL(supportsLegacyGetDisplay || maySupportPlatformGetDisplay);

	if (maySupportPlatformGetDisplayEXT)
	{
		try
		{
			const vector<string> platformExts = eglu::getClientExtensions(egl);
			usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) &&
				de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName()));

		}
		catch (const tcu::NotSupportedError& error)
		{
			// If we can't get the client extension string we must not have EGL 1.5 support or the appropriate extensions.
			maySupportPlatformGetDisplay = false;
			maySupportPlatformGetDisplayEXT = false;
			usePlatformExt = false;
		}
	}

	if (maySupportPlatformGetDisplay)
	{
		display = egl.getPlatformDisplay(nativeDisplay.getPlatformType(), nativeDisplay.getPlatformNative(), nativeDisplay.getPlatformAttributes());
		EGLU_CHECK_MSG(egl, "eglGetPlatformDisplay()");
		TCU_CHECK(display != EGL_NO_DISPLAY);
	}
	else if (usePlatformExt)
	{
		const vector<EGLint>	legacyAttribs	= toLegacyAttribList(nativeDisplay.getPlatformAttributes());

		display = egl.getPlatformDisplayEXT(nativeDisplay.getPlatformType(), nativeDisplay.getPlatformNative(), &legacyAttribs[0]);
		EGLU_CHECK_MSG(egl, "eglGetPlatformDisplayEXT()");
		TCU_CHECK(display != EGL_NO_DISPLAY);
	}
	else if (supportsLegacyGetDisplay)
	{
		display = egl.getDisplay(nativeDisplay.getLegacyNative());
		EGLU_CHECK_MSG(egl, "eglGetDisplay()");
		TCU_CHECK(display != EGL_NO_DISPLAY);
	}
	else
		throw tcu::InternalError("No supported way to get EGL display", DE_NULL, __FILE__, __LINE__);

	DE_ASSERT(display != EGL_NO_DISPLAY);
	return display;
}

EGLDisplay getAndInitDisplay (NativeDisplay& nativeDisplay, Version* version)
{
	const Library&	egl		= nativeDisplay.getLibrary();
	EGLDisplay		display	= getDisplay(nativeDisplay);
	int				major, minor;

	EGLU_CHECK_CALL(egl, initialize(display, &major, &minor));

	if (version)
		*version = Version(major, minor);

	return display;
}

void terminateDisplay(const Library& egl, EGLDisplay display)
{
	EGLU_CHECK_CALL(egl, terminate(display));
}

//! Create EGL window surface using eglCreatePlatformWindowSurface, eglCreateWindowSurface() or eglCreatePlatformWindowSurfaceEXT()
EGLSurface createWindowSurface (NativeDisplay& nativeDisplay, NativeWindow& window, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList)
{
	const Library&	egl									= nativeDisplay.getLibrary();
	const bool		supportsLegacyCreate				= (window.getCapabilities() & NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY) != 0;
	bool			maySupportPlatformCreate				= ((window.getCapabilities() & NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM) != 0
														   && eglu::getVersion(egl, display) >= eglu::Version(1, 5));
	bool			maySupportPlatformCreateExtension		= (window.getCapabilities() & NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM_EXTENSION) != 0;
	bool			usePlatformExt						= false;
	EGLSurface		surface								= EGL_NO_SURFACE;

	TCU_CHECK_INTERNAL(supportsLegacyCreate || maySupportPlatformCreateExtension || maySupportPlatformCreate);

	if (maySupportPlatformCreateExtension)
	{
		try
		{
			const vector<string> platformExts = eglu::getClientExtensions(egl);
			usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) &&
				de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName()));

		}
		catch (const tcu::NotSupportedError& error)
		{
			maySupportPlatformCreate = false;
			maySupportPlatformCreateExtension = false;
			usePlatformExt = false;
		}
	}

	if (maySupportPlatformCreate)
	{
		surface = egl.createPlatformWindowSurface(display, config, window.getPlatformNative(), attribList);
		EGLU_CHECK_MSG(egl, "eglCreatePlatformWindowSurface()");
		TCU_CHECK(surface != EGL_NO_SURFACE);
	}
	else if (usePlatformExt)
	{
		const vector<EGLint>	legacyAttribs	= toLegacyAttribList(attribList);
		surface = egl.createPlatformWindowSurfaceEXT(display, config, window.getPlatformExtension(), &legacyAttribs[0]);
		EGLU_CHECK_MSG(egl, "eglCreatePlatformWindowSurfaceEXT()");
		TCU_CHECK(surface != EGL_NO_SURFACE);
	}
	else if (supportsLegacyCreate)
	{
		const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList);
		surface = egl.createWindowSurface(display, config, window.getLegacyNative(), &legacyAttribs[0]);
		EGLU_CHECK_MSG(egl, "eglCreateWindowSurface()");
		TCU_CHECK(surface != EGL_NO_SURFACE);
	}
	else
		throw tcu::InternalError("No supported way to create EGL window surface", DE_NULL, __FILE__, __LINE__);

	DE_ASSERT(surface != EGL_NO_SURFACE);
	return surface;
}

//! Create EGL pixmap surface using eglCreatePixmapSurface() or eglCreatePlatformPixmapSurfaceEXT()
EGLSurface createPixmapSurface (NativeDisplay& nativeDisplay, NativePixmap& pixmap, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList)
{
	const Library&	egl									= nativeDisplay.getLibrary();
	const bool		supportsLegacyCreate				= (pixmap.getCapabilities() & NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY) != 0;
	bool			maySupportPlatformCreateExtension	= (pixmap.getCapabilities() & NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM_EXTENSION) != 0;
	bool			maySupportPlatformCreate			= ((pixmap.getCapabilities() & NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM) != 0
														   && eglu::getVersion(egl, display) >= eglu::Version(1, 5));
	bool			usePlatformExt						= false;
	EGLSurface		surface								= EGL_NO_SURFACE;

	TCU_CHECK_INTERNAL(supportsLegacyCreate || maySupportPlatformCreateExtension || maySupportPlatformCreate);

	if (maySupportPlatformCreateExtension)
	{
		try
		{
			const vector<string> platformExts = eglu::getClientExtensions(egl);
			usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) &&
				de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName()));

		}
		catch (const tcu::NotSupportedError& error)
		{
			maySupportPlatformCreate = false;
			maySupportPlatformCreateExtension = false;
			usePlatformExt = false;
		}
	}

	if (maySupportPlatformCreate)
	{
		surface = egl.createPlatformPixmapSurface(display, config, pixmap.getPlatformNative(), attribList);
		EGLU_CHECK_MSG(egl, "eglCreatePlatformPixmapSurface()");
		TCU_CHECK(surface != EGL_NO_SURFACE);
	}
	else if (usePlatformExt)
	{
		const vector<EGLint>	legacyAttribs	= toLegacyAttribList(attribList);

		surface = egl.createPlatformPixmapSurfaceEXT(display, config, pixmap.getPlatformExtension(), &legacyAttribs[0]);
		EGLU_CHECK_MSG(egl, "eglCreatePlatformPixmapSurfaceEXT()");
		TCU_CHECK(surface != EGL_NO_SURFACE);
	}
	else if (supportsLegacyCreate)
	{
		const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList);
		surface = egl.createPixmapSurface(display, config, pixmap.getLegacyNative(), &legacyAttribs[0]);
		EGLU_CHECK_MSG(egl, "eglCreatePixmapSurface()");
		TCU_CHECK(surface != EGL_NO_SURFACE);
	}
	else
		throw tcu::InternalError("No supported way to create EGL pixmap surface", DE_NULL, __FILE__, __LINE__);

	DE_ASSERT(surface != EGL_NO_SURFACE);
	return surface;
}

static WindowParams::Visibility getWindowVisibility (tcu::WindowVisibility visibility)
{
	switch (visibility)
	{
		case tcu::WINDOWVISIBILITY_WINDOWED:	return WindowParams::VISIBILITY_VISIBLE;
		case tcu::WINDOWVISIBILITY_FULLSCREEN:	return WindowParams::VISIBILITY_FULLSCREEN;
		case tcu::WINDOWVISIBILITY_HIDDEN:		return WindowParams::VISIBILITY_HIDDEN;

		default:
			DE_ASSERT(false);
			return WindowParams::VISIBILITY_DONT_CARE;
	}
}

WindowParams::Visibility parseWindowVisibility (const tcu::CommandLine& commandLine)
{
	return getWindowVisibility(commandLine.getVisibility());
}

EGLenum parseClientAPI (const std::string& api)
{
	if (api == "OpenGL")
		return EGL_OPENGL_API;
	else if (api == "OpenGL_ES")
		return EGL_OPENGL_ES_API;
	else if (api == "OpenVG")
		return EGL_OPENVG_API;
	else
		throw tcu::InternalError("Unknown EGL client API '" + api + "'");
}

vector<EGLenum> parseClientAPIs (const std::string& apiList)
{
	const vector<string>	apiStrs	= de::splitString(apiList, ' ');
	vector<EGLenum>			apis;

	for (vector<string>::const_iterator api = apiStrs.begin(); api != apiStrs.end(); ++api)
		apis.push_back(parseClientAPI(*api));

	return apis;
}

vector<EGLenum> getClientAPIs (const eglw::Library& egl, eglw::EGLDisplay display)
{
	return parseClientAPIs(egl.queryString(display, EGL_CLIENT_APIS));
}

EGLint getRenderableAPIsMask (const eglw::Library& egl, eglw::EGLDisplay display)
{
	const vector<EGLConfig>	configs	= getConfigs(egl, display);
	EGLint					allAPIs	= 0;

	for (vector<EGLConfig>::const_iterator i = configs.begin(); i != configs.end(); ++i)
		allAPIs |= getConfigAttribInt(egl, display, *i, EGL_RENDERABLE_TYPE);

	return allAPIs;
}

vector<EGLint> toLegacyAttribList (const EGLAttrib* attribs)
{
	const deUint64	attribMask		= 0xffffffffull;	//!< Max bits that can be used
	vector<EGLint>	legacyAttribs;

	if (attribs)
	{
		for (const EGLAttrib* attrib = attribs; *attrib != EGL_NONE; attrib += 2)
		{
			if ((attrib[0] & ~attribMask) || (attrib[1] & ~attribMask))
				throw tcu::InternalError("Failed to translate EGLAttrib to EGLint", DE_NULL, __FILE__, __LINE__);

			legacyAttribs.push_back((EGLint)attrib[0]);
			legacyAttribs.push_back((EGLint)attrib[1]);
		}
	}

	legacyAttribs.push_back(EGL_NONE);

	return legacyAttribs;
}

template<typename Factory>
static const Factory& selectFactory (const tcu::FactoryRegistry<Factory>& registry, const char* objectTypeName, const char* cmdLineArg)
{
	if (cmdLineArg)
	{
		const Factory* factory = registry.getFactoryByName(cmdLineArg);

		if (factory)
			return *factory;
		else
		{
			tcu::print("ERROR: Unknown or unsupported EGL %s type '%s'", objectTypeName, cmdLineArg);
			tcu::print("Available EGL %s types:\n", objectTypeName);
			for (size_t ndx = 0; ndx < registry.getFactoryCount(); ndx++)
				tcu::print("  %s: %s\n", registry.getFactoryByIndex(ndx)->getName(), registry.getFactoryByIndex(ndx)->getDescription());

			TCU_THROW(NotSupportedError, (string("Unsupported or unknown EGL ") + objectTypeName + " type '" + cmdLineArg + "'").c_str());
		}
	}
	else if (!registry.empty())
		return *registry.getDefaultFactory();
	else
		TCU_THROW(NotSupportedError, (string("No factory supporting EGL '") + objectTypeName + "' type").c_str());
}

const NativeDisplayFactory& selectNativeDisplayFactory (const NativeDisplayFactoryRegistry& registry, const tcu::CommandLine& cmdLine)
{
	return selectFactory(registry, "display", cmdLine.getEGLDisplayType());
}

const NativeWindowFactory& selectNativeWindowFactory (const NativeDisplayFactory& factory, const tcu::CommandLine& cmdLine)
{
	return selectFactory(factory.getNativeWindowRegistry(), "window", cmdLine.getEGLWindowType());
}

const NativePixmapFactory& selectNativePixmapFactory (const NativeDisplayFactory& factory, const tcu::CommandLine& cmdLine)
{
	return selectFactory(factory.getNativePixmapRegistry(), "pixmap", cmdLine.getEGLPixmapType());
}

} // eglu
