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

namespace tcu
{
namespace surfaceless
{

class VulkanLibrary : public vk::Library
{
public:
	VulkanLibrary (void)
		: m_library	("libvulkan.so.1")
		, 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);

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

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

	if (!eglChooseConfig(m_eglDisplay, &frame_buffer_attribs[0], &egl_config, 1, &num_configs))
		throw tcu::ResourceError("surfaceless couldn't find any 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();
}
