// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// 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.

#include "VkSemaphore.hpp"

#include "VkConfig.h"

#if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
#  if defined(__linux__) || defined(__ANDROID__)
#    include "VkSemaphoreExternalLinux.hpp"
#  else
#    error "Missing VK_KHR_external_semaphore_fd implementation for this platform!"
#  endif
#elif VK_USE_PLATFORM_FUCHSIA
#include "VkSemaphoreExternalFuchsia.hpp"
#else
#include "VkSemaphoreExternalNone.hpp"
#endif

#include "marl/blockingcall.h"
#include "marl/conditionvariable.h"

#include <functional>
#include <memory>
#include <mutex>
#include <utility>

namespace vk {

// An implementation of VkSemaphore based on Marl primitives.
class Semaphore::Impl
{
public:
	// Create a new instance. The external instance will be allocated only
	// the pCreateInfo->pNext chain indicates it needs to be exported.
	Impl(const VkSemaphoreCreateInfo* pCreateInfo) {
		bool exportSemaphore = false;
		for(const auto* nextInfo = reinterpret_cast<const VkBaseInStructure*>(pCreateInfo->pNext);
			 nextInfo != nullptr; nextInfo = nextInfo->pNext)
		{
			if(nextInfo->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO)
			{
				const auto* exportInfo = reinterpret_cast<const VkExportSemaphoreCreateInfo *>(nextInfo);
				if(exportInfo->handleTypes != External::kExternalSemaphoreHandleType)
				{
					UNIMPLEMENTED("exportInfo->handleTypes");
				}
				exportSemaphore = true;
				break;
			}
		}

		if(exportSemaphore)
		{
			allocateExternalNoInit();
			external->init();
		}
	}

	~Impl() {
		deallocateExternal();
	}

	// Deallocate the External semaphore if any.
	void deallocateExternal()
	{
		if(external)
		{
			external->~External();
			external = nullptr;
		}
	}

	// Allocate the external semaphore.
	// Note that this does not allocate the internal resource, which must be
	// performed by calling external->init(), or importing one using
	// a platform-specific external->importXXX(...) method.
	void allocateExternalNoInit()
	{
		external = new (externalStorage) External();
	}

	void wait()
	{
		if(external)
		{
			if(!external->tryWait())
			{
				// Dispatch the external wait to a background thread.
				// Even if this creates a new thread on each
				// call, it is assumed that this is negligible
				// compared with the actual semaphore wait()
				// operation.
				marl::blocking_call([this](){
					external->wait();
				});
			}

			// If the import was temporary, reset the semaphore to its
			// permanent state by getting rid of |external|.
			// See "6.4.5. Importing Semaphore Payloads" in Vulkan 1.1 spec.
			if(temporaryImport)
			{
				deallocateExternal();
				temporaryImport = false;
			}
		}
		else
		{
			waitInternal();
		}
	}

	void signal()
	{
		if(external)
		{
			// Assumes that signalling an external semaphore is non-blocking,
			// so it can be performed directly either from a fiber or thread.
			external->signal();
		}
		else
		{
			signalInternal();
		}
	}

private:
	// Necessary to make ::importXXX() and ::exportXXX() simpler.
	friend Semaphore;

	void waitInternal()
	{
		// Wait on the marl condition variable only.
		std::unique_lock<std::mutex> lock(mutex);
		condition.wait(lock, [this]{ return this->signaled; });
		signaled = false;  // Vulkan requires resetting after waiting.
	}

	void signalInternal()
	{
		// Signal the marl condition variable only.
		std::unique_lock<std::mutex> lock(mutex);
		if(!signaled)
		{
			signaled = true;
			condition.notify_one();
		}
	}

	// Implementation of a non-external semaphore based on Marl.
	std::mutex mutex;
	marl::ConditionVariable condition;
	bool signaled = false;

	// Optional external semaphore data might be referenced and stored here.
	External* external = nullptr;

	// Set to true if |external| comes from a temporary import.
	bool temporaryImport = false;

	alignas(External) char externalStorage[sizeof(External)];
};

Semaphore::Semaphore(const VkSemaphoreCreateInfo* pCreateInfo, void* mem)
{
	impl = new (mem) Impl(pCreateInfo);
}

void Semaphore::destroy(const VkAllocationCallbacks* pAllocator)
{
	impl->~Impl();
	vk::deallocate(impl, pAllocator);
}

size_t Semaphore::ComputeRequiredAllocationSize(const VkSemaphoreCreateInfo* pCreateInfo)
{
	return sizeof(Semaphore::Impl);
}

void Semaphore::wait()
{
	impl->wait();
}

void Semaphore::signal()
{
	impl->signal();
}

#if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
VkResult Semaphore::importFd(int fd, bool temporaryImport)
{
	std::unique_lock<std::mutex> lock(impl->mutex);
	if(!impl->external)
	{
		impl->allocateExternalNoInit();
	}
	VkResult result = impl->external->importFd(fd);
	if(result != VK_SUCCESS)
	{
		impl->deallocateExternal();
	}
	else
	{
		impl->temporaryImport = temporaryImport;
	}
	return result;
}

VkResult Semaphore::exportFd(int* pFd) const
{
	std::unique_lock<std::mutex> lock(impl->mutex);
	if(!impl->external)
	{
		TRACE("Cannot export non-external semaphore");
		return VK_ERROR_INVALID_EXTERNAL_HANDLE;
	}
	return impl->external->exportFd(pFd);
}
#endif  // SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD

#if VK_USE_PLATFORM_FUCHSIA
VkResult Semaphore::importHandle(zx_handle_t handle, bool temporaryImport)
{
	std::unique_lock<std::mutex> lock(impl->mutex);
	if(!impl->external)
	{
		impl->allocateExternalNoInit();
	}
	// NOTE: Imports are just moving a handle so cannot fail.
	impl->external->importHandle(handle);
	impl->temporaryImport = temporaryImport;
	return VK_SUCCESS;
}

VkResult Semaphore::exportHandle(zx_handle_t *pHandle) const
{
	std::unique_lock<std::mutex> lock(impl->mutex);
	if(!impl->external)
	{
		TRACE("Cannot export non-external semaphore");
		return VK_ERROR_INVALID_EXTERNAL_HANDLE;
	}
	return impl->external->exportHandle(pHandle);
}
#endif  // VK_USE_PLATFORM_FUCHSIA

}  // namespace vk
