/*-------------------------------------------------------------------------
 * 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 = 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 ((red == config.redBits) && (green == config.greenBits) && (blue == config.blueBits) &&
				(alpha == config.alphaBits) && (depth == config.depthBits) &&
				(stencil == config.stencilBits) && (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();
}
