/*-------------------------------------------------------------------------
 * 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 Android EGL platform.
 *//*--------------------------------------------------------------------*/

#include "tcuAndroidPlatform.hpp"
#include "tcuAndroidUtil.hpp"
#include "gluRenderContext.hpp"
#include "egluNativeDisplay.hpp"
#include "egluNativeWindow.hpp"
#include "egluGLContextFactory.hpp"
#include "egluUtil.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"
#include "tcuFunctionLibrary.hpp"
#include "vkWsiPlatform.hpp"

// Assume no call translation is needed
#include <android/native_window.h>
struct egl_native_pixmap_t;
DE_STATIC_ASSERT(sizeof(eglw::EGLNativeDisplayType) == sizeof(void*));
DE_STATIC_ASSERT(sizeof(eglw::EGLNativePixmapType) == sizeof(struct egl_native_pixmap_t*));
DE_STATIC_ASSERT(sizeof(eglw::EGLNativeWindowType) == sizeof(ANativeWindow*));

namespace tcu
{
namespace Android
{

using namespace eglw;

static const eglu::NativeDisplay::Capability	DISPLAY_CAPABILITIES	= eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_LEGACY;
static const eglu::NativeWindow::Capability		WINDOW_CAPABILITIES		= (eglu::NativeWindow::Capability)(eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY |
																										   eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM |
																										   eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM_EXTENSION |
																										   eglu::NativeWindow::CAPABILITY_SET_SURFACE_SIZE |
																										   eglu::NativeWindow::CAPABILITY_GET_SCREEN_SIZE);

class NativeDisplay : public eglu::NativeDisplay
{
public:
									NativeDisplay			(void) : eglu::NativeDisplay(DISPLAY_CAPABILITIES), m_library("libEGL.so") {}
	virtual							~NativeDisplay			(void) {}

	virtual EGLNativeDisplayType	getLegacyNative			(void)			{ return EGL_DEFAULT_DISPLAY;	}
	virtual const eglw::Library&	getLibrary				(void) const	{ return m_library;				}

private:
	eglw::DefaultLibrary			m_library;
};

class NativeDisplayFactory : public eglu::NativeDisplayFactory
{
public:
									NativeDisplayFactory	(WindowRegistry& windowRegistry);
									~NativeDisplayFactory	(void) {}

	virtual eglu::NativeDisplay*	createDisplay			(const EGLAttrib* attribList) const;
};

class NativeWindow : public eglu::NativeWindow
{
public:
									NativeWindow			(Window* window, int width, int height, int32_t format);
	virtual							~NativeWindow			(void);

	virtual EGLNativeWindowType		getLegacyNative			(void)			{ return m_window->getNativeWindow();	}
	virtual EGLNativeWindowType		getPlatformExtension	(void)			{ return m_window->getNativeWindow();	}
	virtual EGLNativeWindowType		getPlatformNative		(void)			{ return m_window->getNativeWindow();	}
	IVec2							getScreenSize			(void) const	{ return m_window->getSize();			}

	void							setSurfaceSize			(IVec2 size);

	virtual void					processEvents			(void);

private:
	Window*							m_window;
	int32_t							m_format;
};

class NativeWindowFactory : public eglu::NativeWindowFactory
{
public:
									NativeWindowFactory		(WindowRegistry& windowRegistry);
									~NativeWindowFactory	(void);

	virtual eglu::NativeWindow*		createWindow			(eglu::NativeDisplay* nativeDisplay, const eglu::WindowParams& params) const;
	virtual eglu::NativeWindow*		createWindow			(eglu::NativeDisplay* nativeDisplay, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, const eglu::WindowParams& params) const;

private:
	virtual eglu::NativeWindow*		createWindow			(const eglu::WindowParams& params, int32_t format) const;

	WindowRegistry&					m_windowRegistry;
};

// NativeWindow

NativeWindow::NativeWindow (Window* window, int width, int height, int32_t format)
	: eglu::NativeWindow	(WINDOW_CAPABILITIES)
	, m_window				(window)
	, m_format				(format)
{
	// Set up buffers.
	setSurfaceSize(IVec2(width, height));
}

NativeWindow::~NativeWindow (void)
{
	m_window->release();
}

void NativeWindow::processEvents (void)
{
	if (m_window->isPendingDestroy())
		throw eglu::WindowDestroyedError("Window has been destroyed");
}

void NativeWindow::setSurfaceSize (tcu::IVec2 size)
{
	m_window->setBuffersGeometry(size.x() != eglu::WindowParams::SIZE_DONT_CARE ? size.x() : 0,
								 size.y() != eglu::WindowParams::SIZE_DONT_CARE ? size.y() : 0,
								 m_format);
}

// NativeWindowFactory

NativeWindowFactory::NativeWindowFactory (WindowRegistry& windowRegistry)
	: eglu::NativeWindowFactory	("default", "Default display", WINDOW_CAPABILITIES)
	, m_windowRegistry			(windowRegistry)
{
}

NativeWindowFactory::~NativeWindowFactory (void)
{
}

eglu::NativeWindow* NativeWindowFactory::createWindow (eglu::NativeDisplay* nativeDisplay, const eglu::WindowParams& params) const
{
	DE_UNREF(nativeDisplay);
	return createWindow(params, WINDOW_FORMAT_RGBA_8888);
}

eglu::NativeWindow* NativeWindowFactory::createWindow (eglu::NativeDisplay* nativeDisplay, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, const eglu::WindowParams& params) const
{
	const int32_t format = (int32_t)eglu::getConfigAttribInt(nativeDisplay->getLibrary(), display, config, EGL_NATIVE_VISUAL_ID);
	DE_UNREF(nativeDisplay && attribList);
	return createWindow(params, format);
}

eglu::NativeWindow* NativeWindowFactory::createWindow (const eglu::WindowParams& params, int32_t format) const
{
	Window* window = m_windowRegistry.tryAcquireWindow();

	if (!window)
		throw ResourceError("Native window is not available", DE_NULL, __FILE__, __LINE__);

	return new NativeWindow(window, params.width, params.height, format);
}

// NativeDisplayFactory

NativeDisplayFactory::NativeDisplayFactory (WindowRegistry& windowRegistry)
	: eglu::NativeDisplayFactory("default", "Default display", DISPLAY_CAPABILITIES)
{
	m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(windowRegistry));
}

eglu::NativeDisplay* NativeDisplayFactory::createDisplay (const EGLAttrib* attribList) const
{
	DE_UNREF(attribList);
	return new NativeDisplay();
}

// Vulkan

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

DE_STATIC_ASSERT(sizeof(vk::pt::AndroidNativeWindowPtr) == sizeof(ANativeWindow*));

class VulkanWindow : public vk::wsi::AndroidWindowInterface
{
public:
	VulkanWindow (tcu::Android::Window& window)
		: vk::wsi::AndroidWindowInterface	(vk::pt::AndroidNativeWindowPtr(window.getNativeWindow()))
		, m_window							(window)
	{
	}

	void setVisible(bool visible)
	{
		DE_UNREF(visible);
	}

	void resize(const UVec2& newSize)
	{
		DE_UNREF(newSize);
	}

	~VulkanWindow (void)
	{
		m_window.release();
	}

private:
	tcu::Android::Window&	m_window;
};

class VulkanDisplay : public vk::wsi::Display
{
public:
	VulkanDisplay (WindowRegistry& windowRegistry)
		: m_windowRegistry(windowRegistry)
	{
	}

	vk::wsi::Window* createWindow (const Maybe<UVec2>& initialSize) const
	{
		Window* const	window	= m_windowRegistry.tryAcquireWindow();

		if (window)
		{
			try
			{
				if (initialSize)
					window->setBuffersGeometry((int)initialSize->x(), (int)initialSize->y(), WINDOW_FORMAT_RGBA_8888);

				return new VulkanWindow(*window);
			}
			catch (...)
			{
				window->release();
				throw;
			}
		}
		else
			TCU_THROW(ResourceError, "Native window is not available");
	}

private:
	WindowRegistry&		m_windowRegistry;
};

static size_t getTotalSystemMemory (ANativeActivity* activity)
{
	const size_t	MiB		= (size_t)(1<<20);

	try
	{
		const size_t totalMemory = getTotalAndroidSystemMemory(activity);
		print("Device has %.2f MiB of system memory\n", static_cast<double>(totalMemory) / static_cast<double>(MiB));
		return totalMemory;
	}
	catch (const std::exception& e)
	{
		// Use relatively high fallback size to encourage CDD-compliant behavior
		const size_t	fallbackSize	= (sizeof(void*) == sizeof(deUint64)) ? 2048*MiB : 1024*MiB;

		print("WARNING: Failed to determine system memory size required by CDD: %s\n", e.what());
		print("WARNING: Using fall-back size of %.2f MiB\n", double(fallbackSize) / double(MiB));

		return fallbackSize;
	}
}

// Platform

Platform::Platform (NativeActivity& activity)
	: m_activity			(activity)
	, m_totalSystemMemory	(getTotalSystemMemory(activity.getNativeActivity()))
{
	m_nativeDisplayFactoryRegistry.registerFactory(new NativeDisplayFactory(m_windowRegistry));
	m_contextFactoryRegistry.registerFactory(new eglu::GLContextFactory(m_nativeDisplayFactoryRegistry));
}

Platform::~Platform (void)
{
}

bool Platform::processEvents (void)
{
	m_windowRegistry.garbageCollect();
	return true;
}

vk::Library* Platform::createLibrary (void) const
{
	return new VulkanLibrary();
}

void Platform::describePlatform (std::ostream& dst) const
{
	tcu::Android::describePlatform(m_activity.getNativeActivity(), dst);
}

void Platform::getMemoryLimits (vk::PlatformMemoryLimits& limits) const
{
	// Worst-case estimates
	const size_t	MiB				= (size_t)(1<<20);
	const size_t	baseMemUsage	= 400*MiB;
	const double	safeUsageRatio	= 0.25;

	limits.totalSystemMemory					= de::max((size_t)(double(deInt64(m_totalSystemMemory)-deInt64(baseMemUsage)) * safeUsageRatio), 16*MiB);

	// Assume UMA architecture
	limits.totalDeviceLocalMemory				= 0;

	// Reasonable worst-case estimates
	limits.deviceMemoryAllocationGranularity	= 64*1024;
	limits.devicePageSize						= 4096;
	limits.devicePageTableEntrySize				= 8;
	limits.devicePageTableHierarchyLevels		= 3;
}

vk::wsi::Display* Platform::createWsiDisplay (vk::wsi::Type wsiType) const
{
	if (wsiType == vk::wsi::TYPE_ANDROID)
		return new VulkanDisplay(const_cast<WindowRegistry&>(m_windowRegistry));
	else
		TCU_THROW(NotSupportedError, "WSI type not supported on Android");
}

bool Platform::hasDisplay (vk::wsi::Type wsiType) const
{
	if (wsiType == vk::wsi::TYPE_ANDROID)
		return true;

	return false;
}

} // Android
} // tcu
