// Copyright 2016 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 "GrallocAndroid.hpp"
#include "Debug.hpp"

#ifdef HAVE_GRALLOC1
#	include <sync/sync.h>
#endif
#ifdef HAVE_GRALLOC3
using V3Error = android::hardware::graphics::mapper::V3_0::Error;
using V3Mapper = android::hardware::graphics::mapper::V3_0::IMapper;
using android::hardware::hidl_handle;
#endif

GrallocModule *GrallocModule::getInstance()
{
	static GrallocModule instance;
	return &instance;
}

GrallocModule::GrallocModule()
{
#ifdef HAVE_GRALLOC3
	m_gralloc3_mapper = V3Mapper::getService();
	if(m_gralloc3_mapper != nullptr)
	{
		return;
	}
#endif

	const hw_module_t *module = nullptr;
	hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);

	m_major_version = (module->module_api_version >> 8) & 0xff;
	switch(m_major_version)
	{
		case 0:
			m_module = reinterpret_cast<const gralloc_module_t *>(module);
			break;
		case 1:
#ifdef HAVE_GRALLOC1
			gralloc1_open(module, &m_gralloc1_device);
			m_gralloc1_lock = (GRALLOC1_PFN_LOCK)m_gralloc1_device->getFunction(m_gralloc1_device, GRALLOC1_FUNCTION_LOCK);
			m_gralloc1_unlock = (GRALLOC1_PFN_UNLOCK)m_gralloc1_device->getFunction(m_gralloc1_device, GRALLOC1_FUNCTION_UNLOCK);
			break;
#endif
		default:
			TRACE("unknown gralloc major version (%d)", m_major_version);
			break;
	}
}

int GrallocModule::import(buffer_handle_t handle, buffer_handle_t *imported_handle)
{
#ifdef HAVE_GRALLOC3
	if(m_gralloc3_mapper != nullptr)
	{
		V3Error error;
		auto ret = m_gralloc3_mapper->importBuffer(handle,
		                                           [&](const auto &tmp_err, const auto &tmp_buf) {
			                                           error = tmp_err;
			                                           if(error == V3Error::NONE)
			                                           {
				                                           *imported_handle = static_cast<buffer_handle_t>(tmp_buf);
			                                           }
		                                           });
		return ret.isOk() && error == V3Error::NONE ? 0 : -1;
	}
#endif

	*imported_handle = handle;
	return 0;
}

int GrallocModule::release(buffer_handle_t handle)
{
#ifdef HAVE_GRALLOC3
	if(m_gralloc3_mapper != nullptr)
	{
		native_handle_t *native_handle = const_cast<native_handle_t *>(handle);
		return m_gralloc3_mapper->freeBuffer(native_handle).isOk() ? 0 : 1;
	}
#endif

	return 0;
}

int GrallocModule::lock(buffer_handle_t handle, int usage, int left, int top, int width, int height, void **vaddr)
{
#ifdef HAVE_GRALLOC3
	if(m_gralloc3_mapper != nullptr)
	{
		native_handle_t *native_handle = const_cast<native_handle_t *>(handle);

		V3Mapper::Rect rect;
		rect.left = left;
		rect.top = top;
		rect.width = width;
		rect.height = height;

		hidl_handle empty_fence_handle;

		V3Error error;
		auto ret = m_gralloc3_mapper->lock(native_handle, usage, rect, empty_fence_handle,
		                                   [&](const auto &tmp_err,
		                                       const auto &tmp_vaddr,
		                                       const auto & /*bytes_per_pixel*/,
		                                       const auto & /*bytes_per_stride*/) {
			                                   error = tmp_err;
			                                   if(tmp_err == V3Error::NONE)
			                                   {
				                                   *vaddr = tmp_vaddr;
			                                   }
		                                   });
		return ret.isOk() && error == V3Error::NONE ? 0 : -1;
	}
#endif

	switch(m_major_version)
	{
		case 0:
		{
			return m_module->lock(m_module, handle, usage, left, top, width, height, vaddr);
		}
		case 1:
#ifdef HAVE_GRALLOC1
		{
			gralloc1_rect_t outRect{};
			outRect.left = left;
			outRect.top = top;
			outRect.width = width;
			outRect.height = height;
			return m_gralloc1_lock(m_gralloc1_device, handle, usage, usage, &outRect, vaddr, -1);
		}
#endif
		default:
		{
			TRACE("no gralloc module to lock");
			return -1;
		}
	}
}

int GrallocModule::unlock(buffer_handle_t handle)
{
#ifdef HAVE_GRALLOC3
	if(m_gralloc3_mapper != nullptr)
	{
		native_handle_t *native_handle = const_cast<native_handle_t *>(handle);

		V3Error error;
		auto ret = m_gralloc3_mapper->unlock(native_handle,
		                                     [&](const auto &tmp_err, const auto &) {
			                                     error = tmp_err;
		                                     });
		return ret.isOk() && error == V3Error::NONE ? 0 : -1;
	}
#endif

	switch(m_major_version)
	{
		case 0:
		{
			return m_module->unlock(m_module, handle);
		}
		case 1:
#ifdef HAVE_GRALLOC1
		{
			int32_t fenceFd = -1;
			int error = m_gralloc1_unlock(m_gralloc1_device, handle, &fenceFd);
			if(!error)
			{
				sync_wait(fenceFd, -1);
				close(fenceFd);
			}
			return error;
		}
#endif
		default:
		{
			TRACE("no gralloc module to unlock");
			return -1;
		}
	}
}
