/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright 2015 Intel Corporation
 *
 * 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 surfaceless platform
 *//*--------------------------------------------------------------------*/

#include "tcuSurfacelessPlatform.hpp"

#include <string>
#include <vector>
#include <sys/utsname.h>

#include "deDynamicLibrary.hpp"
#include "deMemory.h"
#include "deSTLUtil.hpp"
#include "egluUtil.hpp"
#include "egluGLUtil.hpp"
#include "eglwEnums.hpp"
#include "eglwLibrary.hpp"
#include "gluPlatform.hpp"
#include "gluRenderConfig.hpp"
#include "glwInitES20Direct.hpp"
#include "glwInitES30Direct.hpp"
#include "glwInitFunctions.hpp"
#include "tcuFunctionLibrary.hpp"
#include "tcuPixelFormat.hpp"
#include "tcuPlatform.hpp"
#include "tcuRenderTarget.hpp"
#include "vkPlatform.hpp"

#include <EGL/egl.h>

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

#if !defined(EGL_KHR_create_context)
	#define EGL_CONTEXT_FLAGS_KHR					0x30FC
	#define EGL_CONTEXT_MAJOR_VERSION_KHR				0x3098
	#define EGL_CONTEXT_MINOR_VERSION_KHR				0x30FB
	#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR	0x00000002
	#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR			0x00000001
	#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR			0x00000001
	#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR		0x00000002
	#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR			0x30FD
	#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR	0x31BD
	#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR		0x00000004
	#define EGL_KHR_create_context					1
	#define EGL_LOSE_CONTEXT_ON_RESET_KHR				0x31BF
	#define EGL_NO_RESET_NOTIFICATION_KHR				0x31BE
	#define EGL_OPENGL_ES3_BIT_KHR					0x00000040
#endif // EGL_KHR_create_context

// Default library names
#if !defined(DEQP_GLES2_LIBRARY_PATH)
#	define DEQP_GLES2_LIBRARY_PATH "libGLESv2.so"
#endif

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

#if !defined(DEQP_OPENGL_LIBRARY_PATH)
#	define DEQP_OPENGL_LIBRARY_PATH "libGL.so"
#endif

#if !defined(DEQP_VULKAN_LIBRARY_PATH)
#	if (DE_OS == DE_OS_ANDROID)
#		define DEQP_VULKAN_LIBRARY_PATH "libvulkan.so"
#	else
#		define DEQP_VULKAN_LIBRARY_PATH "libvulkan.so.1"
#	endif
#endif

namespace tcu
{
namespace surfaceless
{

class VulkanLibrary : public vk::Library
{
public:
	VulkanLibrary (void)
		: m_library	(DEQP_VULKAN_LIBRARY_PATH)
		, m_driver	(m_library)
	{
	}

	const vk::PlatformInterface& getPlatformInterface (void) const
	{
		return m_driver;
	}
	const tcu::FunctionLibrary&		getFunctionLibrary		(void) const
	{
		return m_library;
	}
private:
	const tcu::DynamicFunctionLibrary	m_library;
	const vk::PlatformDriver			m_driver;
};

// Copied from tcuX11Platform.cpp
class VulkanPlatform : public vk::Platform
{
public:
	vk::Library* createLibrary (void) const
	{
		return new VulkanLibrary();
	}

	void describePlatform (std::ostream& dst) const
	{
		utsname		sysInfo;

		deMemset(&sysInfo, 0, sizeof(sysInfo));

		if (uname(&sysInfo) != 0)
			throw std::runtime_error("uname() failed");

		dst << "OS: " << sysInfo.sysname << " " << sysInfo.release << " " << sysInfo.version << "\n";
		dst << "CPU: " << sysInfo.machine << "\n";
	}

	// FINISHME: Query actual memory limits.
	//
	// These hard-coded memory limits were copied from tcuX11Platform.cpp,
	// and they work well enough for Intel platforms.
	void getMemoryLimits (vk::PlatformMemoryLimits& limits) const
	{
		limits.totalSystemMemory					= 256*1024*1024;
		limits.totalDeviceLocalMemory				= 128*1024*1024;
		limits.deviceMemoryAllocationGranularity	= 64*1024;
		limits.devicePageSize						= 4096;
		limits.devicePageTableEntrySize				= 8;
		limits.devicePageTableHierarchyLevels		= 3;
	}
};

bool isEGLExtensionSupported(
		const eglw::Library& egl,
		eglw::EGLDisplay,
		const std::string& extName)
{
	const vector<string> exts = eglu::getClientExtensions(egl);
	return de::contains(exts.begin(), exts.end(), extName);
}

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

	glw::GenericFuncType get(const char* name) const
	{
		return (glw::GenericFuncType)m_egl.getProcAddress(name);
	}
protected:
	const eglw::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 Platform : public tcu::Platform, public glu::Platform
{
public:
					Platform	(void);
	const glu::Platform&		getGLPlatform	(void) const { return *this; }
	const vk::Platform&			getVulkanPlatform	(void) const { return m_vkPlatform; }

private:
	VulkanPlatform		m_vkPlatform;
};

class ContextFactory : public glu::ContextFactory
{
public:
					ContextFactory	(void);
	glu::RenderContext*		createContext	(const glu::RenderConfig& config, const tcu::CommandLine&, const glu::RenderContext*) const;
};

class EglRenderContext : public glu::RenderContext
{
public:
					EglRenderContext(const glu::RenderConfig& config, const tcu::CommandLine& cmdLine);
					~EglRenderContext(void);

	glu::ContextType		getType		(void) const	{ return m_contextType; }
	const glw::Functions&		getFunctions	(void) const	{ return m_glFunctions; }
	const tcu::RenderTarget&	getRenderTarget	(void) const;
	void				postIterate	(void);

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

private:
	const eglw::DefaultLibrary      m_egl;
	const glu::ContextType		m_contextType;
	eglw::EGLDisplay		m_eglDisplay;
	eglw::EGLContext		m_eglContext;
	de::DynamicLibrary*		m_glLibrary;
	glw::Functions			m_glFunctions;
	tcu::RenderTarget		m_renderTarget;
};

Platform::Platform(void)
{
	m_contextFactoryRegistry.registerFactory(new ContextFactory());
}

ContextFactory::ContextFactory()
	: glu::ContextFactory("default", "EGL surfaceless context")
{}

glu::RenderContext* ContextFactory::createContext(const glu::RenderConfig& config, const tcu::CommandLine& cmdLine, const glu::RenderContext*) const
{
	return new EglRenderContext(config, cmdLine);
}

EglRenderContext::EglRenderContext(const glu::RenderConfig& config, const tcu::CommandLine& cmdLine)
	: m_egl("libEGL.so")
	, m_contextType(config.type)
	, m_eglDisplay(EGL_NO_DISPLAY)
	, m_eglContext(EGL_NO_CONTEXT)
	, m_renderTarget(
			config.width,
			config.height,
			tcu::PixelFormat(
					config.redBits,
					config.greenBits,
					config.blueBits,
					config.alphaBits),
			config.depthBits,
			config.stencilBits,
			config.numSamples)

{
	vector<eglw::EGLint>	context_attribs;
	vector<eglw::EGLint>	frame_buffer_attribs;
	vector<eglw::EGLint>	surface_attribs;

	const glu::ContextType&	contextType = config.type;
	eglw::EGLint		eglMajorVersion;
	eglw::EGLint		eglMinorVersion;
	eglw::EGLint		flags = 0;
	eglw::EGLint		num_configs;
	eglw::EGLConfig		egl_config = NULL;
	eglw::EGLSurface	egl_surface;

	(void) cmdLine;

	m_eglDisplay = m_egl.getDisplay(NULL);
	EGLU_CHECK_MSG(m_egl, "eglGetDisplay()");
	if (m_eglDisplay == EGL_NO_DISPLAY)
		throw tcu::ResourceError("eglGetDisplay() failed");

	EGLU_CHECK_CALL(m_egl, initialize(m_eglDisplay, &eglMajorVersion, &eglMinorVersion));

	frame_buffer_attribs.push_back(EGL_RENDERABLE_TYPE);
	switch(contextType.getMajorVersion())
	{
		case 3:
			frame_buffer_attribs.push_back(EGL_OPENGL_ES3_BIT);
			break;
		case 2:
			frame_buffer_attribs.push_back(EGL_OPENGL_ES2_BIT);
			break;
		default:
			frame_buffer_attribs.push_back(EGL_OPENGL_ES_BIT);
	}

	frame_buffer_attribs.push_back(EGL_SURFACE_TYPE);
	switch (config.surfaceType)
	{
		case glu::RenderConfig::SURFACETYPE_DONT_CARE:
			frame_buffer_attribs.push_back(EGL_DONT_CARE);
			break;
		case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:
		case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:
			frame_buffer_attribs.push_back(EGL_PBUFFER_BIT);
			surface_attribs.push_back(EGL_WIDTH);
			surface_attribs.push_back(config.width);
			surface_attribs.push_back(EGL_HEIGHT);
			surface_attribs.push_back(config.height);
			break;
		case glu::RenderConfig::SURFACETYPE_WINDOW:
			throw tcu::NotSupportedError("surfaceless platform does not support --deqp-surface-type=window");
		case glu::RenderConfig::SURFACETYPE_LAST:
			TCU_CHECK_INTERNAL(false);
	}

	surface_attribs.push_back(EGL_NONE);

	frame_buffer_attribs.push_back(EGL_RED_SIZE);
	frame_buffer_attribs.push_back(config.redBits);

	frame_buffer_attribs.push_back(EGL_GREEN_SIZE);
	frame_buffer_attribs.push_back(config.greenBits);

	frame_buffer_attribs.push_back(EGL_BLUE_SIZE);
	frame_buffer_attribs.push_back(config.blueBits);

	frame_buffer_attribs.push_back(EGL_ALPHA_SIZE);
	frame_buffer_attribs.push_back(config.alphaBits);

	frame_buffer_attribs.push_back(EGL_DEPTH_SIZE);
	frame_buffer_attribs.push_back(config.depthBits);

	frame_buffer_attribs.push_back(EGL_STENCIL_SIZE);
	frame_buffer_attribs.push_back(config.stencilBits);

	frame_buffer_attribs.push_back(EGL_SAMPLES);
	frame_buffer_attribs.push_back(config.numSamples);

	frame_buffer_attribs.push_back(EGL_NONE);

	if (!eglChooseConfig(m_eglDisplay, &frame_buffer_attribs[0], NULL, 0, &num_configs))
		throw tcu::ResourceError("surfaceless couldn't find any config");

	eglw::EGLConfig		all_configs[num_configs];

	if (!eglChooseConfig(m_eglDisplay, &frame_buffer_attribs[0], all_configs, num_configs, &num_configs))
		throw tcu::ResourceError("surfaceless couldn't find any config");

	for (int i = 0; i < num_configs; i++) {
		EGLint red, green, blue, alpha, depth, stencil, samples;
		eglGetConfigAttrib(m_eglDisplay, all_configs[i], EGL_RED_SIZE, &red);
		eglGetConfigAttrib(m_eglDisplay, all_configs[i], EGL_GREEN_SIZE, &green);
		eglGetConfigAttrib(m_eglDisplay, all_configs[i], EGL_BLUE_SIZE, &blue);
		eglGetConfigAttrib(m_eglDisplay, all_configs[i], EGL_ALPHA_SIZE, &alpha);
		eglGetConfigAttrib(m_eglDisplay, all_configs[i], EGL_DEPTH_SIZE, &depth);
		eglGetConfigAttrib(m_eglDisplay, all_configs[i], EGL_STENCIL_SIZE, &stencil);
		eglGetConfigAttrib(m_eglDisplay, all_configs[i], EGL_SAMPLES, &samples);

		if (
				(glu::RenderConfig::DONT_CARE == config.redBits		|| red		== config.redBits)		&&
				(glu::RenderConfig::DONT_CARE == config.greenBits	|| green	== config.greenBits)	&&
				(glu::RenderConfig::DONT_CARE == config.blueBits	|| blue		== config.blueBits)		&&
				(glu::RenderConfig::DONT_CARE == config.alphaBits	|| alpha	== config.alphaBits)	&&
				(glu::RenderConfig::DONT_CARE == config.depthBits	|| depth	== config.depthBits)	&&
				(glu::RenderConfig::DONT_CARE == config.stencilBits	|| stencil	== config.stencilBits)	&&
				(glu::RenderConfig::DONT_CARE == config.numSamples	|| samples	== config.numSamples)) {
			egl_config = all_configs[i];
			break;
		}
	}

	if (!egl_config)
		throw tcu::ResourceError("surfaceless couldn't find a matching config");

	switch (config.surfaceType)
	{
		case glu::RenderConfig::SURFACETYPE_DONT_CARE:
			egl_surface = EGL_NO_SURFACE;
			break;
		case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:
		case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:
			egl_surface = eglCreatePbufferSurface(m_eglDisplay, egl_config, &surface_attribs[0]);
			break;
		case glu::RenderConfig::SURFACETYPE_WINDOW:
		case glu::RenderConfig::SURFACETYPE_LAST:
			TCU_CHECK_INTERNAL(false);
	}

	context_attribs.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
	context_attribs.push_back(contextType.getMajorVersion());
	context_attribs.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
	context_attribs.push_back(contextType.getMinorVersion());

	switch (contextType.getProfile())
	{
		case glu::PROFILE_ES:
			EGLU_CHECK_CALL(m_egl, bindAPI(EGL_OPENGL_ES_API));
			break;
		case glu::PROFILE_CORE:
			EGLU_CHECK_CALL(m_egl, bindAPI(EGL_OPENGL_API));
			context_attribs.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
			context_attribs.push_back(EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR);
			break;
		case glu::PROFILE_COMPATIBILITY:
			EGLU_CHECK_CALL(m_egl, bindAPI(EGL_OPENGL_API));
			context_attribs.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
			context_attribs.push_back(EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
			break;
		case glu::PROFILE_LAST:
			TCU_CHECK_INTERNAL(false);
	}

	if ((contextType.getFlags() & glu::CONTEXT_DEBUG) != 0)
		flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;

	if ((contextType.getFlags() & glu::CONTEXT_ROBUST) != 0)
		flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;

	if ((contextType.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0)
		flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;

	context_attribs.push_back(EGL_CONTEXT_FLAGS_KHR);
	context_attribs.push_back(flags);

	context_attribs.push_back(EGL_NONE);

	m_eglContext = m_egl.createContext(m_eglDisplay, egl_config, EGL_NO_CONTEXT, &context_attribs[0]);
	EGLU_CHECK_MSG(m_egl, "eglCreateContext()");
	if (!m_eglContext)
		throw tcu::ResourceError("eglCreateContext failed");

	EGLU_CHECK_CALL(m_egl, makeCurrent(m_eglDisplay, egl_surface, egl_surface, m_eglContext));

	if ((eglMajorVersion == 1 && eglMinorVersion >= 5) ||
		isEGLExtensionSupported(m_egl, m_eglDisplay, "EGL_KHR_get_all_proc_addresses") ||
		isEGLExtensionSupported(m_egl, EGL_NO_DISPLAY, "EGL_KHR_client_get_all_proc_addresses"))
	{
		// Use eglGetProcAddress() for core functions
		GetProcFuncLoader funcLoader(m_egl);
		glu::initCoreFunctions(&m_glFunctions, &funcLoader, contextType.getAPI());
	}
#if !defined(DEQP_GLES2_RUNTIME_LOAD)
	else if (contextType.getAPI() == glu::ApiType::es(2,0))
	{
		glw::initES20Direct(&m_glFunctions);
	}
#endif
#if !defined(DEQP_GLES3_RUNTIME_LOAD)
	else if (contextType.getAPI() == glu::ApiType::es(3,0))
	{
		glw::initES30Direct(&m_glFunctions);
	}
#endif
	else
	{
		const char* libraryPath = NULL;

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

		m_glLibrary = new de::DynamicLibrary(libraryPath);

		DynamicFuncLoader funcLoader(m_glLibrary);
		glu::initCoreFunctions(&m_glFunctions, &funcLoader, contextType.getAPI());
	}

	{
		GetProcFuncLoader extLoader(m_egl);
		glu::initExtensionFunctions(&m_glFunctions, &extLoader, contextType.getAPI());
	}
}

EglRenderContext::~EglRenderContext(void)
{
	try
	{
		if (m_eglDisplay != EGL_NO_DISPLAY)
		{
			EGLU_CHECK_CALL(m_egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));

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

		EGLU_CHECK_CALL(m_egl, terminate(m_eglDisplay));
	}
	catch (...)
	{
	}
}

const tcu::RenderTarget& EglRenderContext::getRenderTarget(void) const
{
	return m_renderTarget;
}

void EglRenderContext::postIterate(void)
{
	this->getFunctions().finish();
}

} // namespace surfaceless
} // namespace tcu

tcu::Platform* createPlatform(void)
{
	return new tcu::surfaceless::Platform();
}
