/*-------------------------------------------------------------------------
 * drawElements Quality Program EGL Module
 * ---------------------------------------
 *
 * 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-specific operations.
 *//*--------------------------------------------------------------------*/

#include "teglAndroidUtil.hpp"

#include "deStringUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "gluTextureUtil.hpp"
#include "glwEnums.hpp"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"

namespace deqp
{
namespace egl
{
namespace Image
{

using std::string;
using de::MovePtr;
using tcu::PixelBufferAccess;
using tcu::TextureFormat;
using tcu::Texture2D;
using eglu::AttribMap;
using namespace glw;
using namespace eglw;

#if (DE_OS != DE_OS_ANDROID)

MovePtr<ImageSource> createAndroidNativeImageSource	(GLenum format, deUint32 numLayers, bool isYUV)
{
	DE_UNREF(numLayers);
	return createUnsupportedImageSource("Not Android platform", format, isYUV);
}

#else // DE_OS == DE_OS_ANDROID

#if defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
#	define BUILT_WITH_ANDROID_HARDWARE_BUFFER 1
#endif

#if defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
#	define BUILT_WITH_ANDROID_P_HARDWARE_BUFFER 1
#endif

#if !defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)

MovePtr<ImageSource> createAndroidNativeImageSource	(GLenum format, deUint32 numLayers, bool isYUV)
{
	DE_UNREF(numLayers);
	return createUnsupportedImageSource("AHB API not supported", format, isYUV);
}

#else // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)

namespace
{

#include <sys/system_properties.h>
#include <android/hardware_buffer.h>
#include "deDynamicLibrary.hpp"

const deUint32 AHB_FORMAT_Y8Cb8Cr8_420 = 0x23;

deInt32 androidGetSdkVersion (void)
{
	static deInt32 sdkVersion = -1;
	if (sdkVersion < 0)
	{
		char value[128] = {0};
		__system_property_get("ro.build.version.sdk", value);
		sdkVersion = static_cast<deInt32>(strtol(value, DE_NULL, 10));
		printf("SDK Version is %d\n", sdkVersion);
	}
	return sdkVersion;
}

typedef int		(*pfnAHardwareBuffer_allocate)(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer);
typedef void	(*pfnAHardwareBuffer_describe)(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc);
typedef void	(*pfnAHardwareBuffer_acquire)(AHardwareBuffer* buffer);
typedef void	(*pfnAHardwareBuffer_release)(AHardwareBuffer* buffer);
typedef int		(*pfnAHardwareBuffer_isSupported)(const AHardwareBuffer_Desc* desc);

struct AhbFunctions
{
	pfnAHardwareBuffer_allocate		allocate;
	pfnAHardwareBuffer_describe		describe;
	pfnAHardwareBuffer_acquire		acquire;
	pfnAHardwareBuffer_release		release;
	pfnAHardwareBuffer_isSupported	isSupported;
};

AhbFunctions ahbFunctions;

bool ahbFunctionsLoaded (AhbFunctions* pAhbFunctions, deInt32 sdkVersion)
{
	static bool ahbApiLoaded = false;
	if (ahbApiLoaded ||
			((pAhbFunctions->allocate != DE_NULL) &&
			 (pAhbFunctions->describe != DE_NULL) &&
			 (pAhbFunctions->acquire  != DE_NULL) &&
			 (pAhbFunctions->release  != DE_NULL) &&
			 (pAhbFunctions->isSupported != DE_NULL || sdkVersion < 29)))
	{
		ahbApiLoaded = true;
		return true;
	}
	return false;
}

bool loadAhbDynamicApis (deInt32 sdkVersion)
{
	if (!ahbFunctionsLoaded(&ahbFunctions, sdkVersion))
	{
		static de::DynamicLibrary libnativewindow("libnativewindow.so");
		ahbFunctions.allocate = reinterpret_cast<pfnAHardwareBuffer_allocate>(libnativewindow.getFunction("AHardwareBuffer_allocate"));
		ahbFunctions.describe = reinterpret_cast<pfnAHardwareBuffer_describe>(libnativewindow.getFunction("AHardwareBuffer_describe"));
		ahbFunctions.acquire  = reinterpret_cast<pfnAHardwareBuffer_acquire>(libnativewindow.getFunction("AHardwareBuffer_acquire"));
		ahbFunctions.release  = reinterpret_cast<pfnAHardwareBuffer_release>(libnativewindow.getFunction("AHardwareBuffer_release"));
		if (sdkVersion >= 29)
			ahbFunctions.isSupported = reinterpret_cast<pfnAHardwareBuffer_isSupported>(libnativewindow.getFunction("AHardwareBuffer_isSupported"));
		else
			ahbFunctions.isSupported = DE_NULL;

		return ahbFunctionsLoaded(&ahbFunctions, sdkVersion);
	}

	return true;
}

deUint32 getPixelFormat (GLenum format)
{
	switch (format)
	{
		case GL_RGB565:				return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
		case GL_RGB8:				return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
		case GL_RGBA8:				return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
		case GL_DEPTH_COMPONENT16:	return AHARDWAREBUFFER_FORMAT_D16_UNORM;
		case GL_DEPTH_COMPONENT24:	return AHARDWAREBUFFER_FORMAT_D24_UNORM;
		case GL_DEPTH24_STENCIL8:	return AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT;
		case GL_DEPTH_COMPONENT32F:	return AHARDWAREBUFFER_FORMAT_D32_FLOAT;
		case GL_DEPTH32F_STENCIL8:	return AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT;
		case GL_RGB10_A2:			return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
		case GL_RGBA16F:			return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
		case GL_STENCIL_INDEX8:		return AHARDWAREBUFFER_FORMAT_S8_UINT;

		default:					TCU_THROW(NotSupportedError, "Texture format unsupported by Android");
	}
}

class AndroidNativeClientBuffer : public ClientBuffer
{
public:
						AndroidNativeClientBuffer	(const Library& egl, GLenum format, deUint32 numLayers, bool isYUV);
						~AndroidNativeClientBuffer	(void);
	EGLClientBuffer		get							(void) const;
	void				lock						(void** data);
	void				unlock						(void);
	AHardwareBuffer_Desc	describe					(void);

private:
	const Library&			m_egl;
	AHardwareBuffer*		m_hardwareBuffer;
};

AndroidNativeClientBuffer::AndroidNativeClientBuffer (const Library& egl, GLenum format, deUint32 numLayers, bool isYUV)
	: m_egl(egl)
{
	deInt32 sdkVersion = androidGetSdkVersion();

#if defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
	// When testing AHB on Android-P and newer the CTS must be compiled against API28 or newer.
	DE_TEST_ASSERT(sdkVersion >= 28); /*__ANDROID_API_P__ */
#else
	// When testing AHB on Android-O and newer the CTS must be compiled against API26 or newer.
	DE_TEST_ASSERT(sdkVersion >= 26); /* __ANDROID_API_O__ */
#endif // !defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)

	if (!loadAhbDynamicApis(sdkVersion))
	{
		// Couldn't load Android AHB system APIs.
		DE_TEST_ASSERT(false);
	}

	AHardwareBuffer_Desc hbufferdesc = {
		64u,
		64u,
		numLayers,
		isYUV ? AHB_FORMAT_Y8Cb8Cr8_420 : getPixelFormat(format),
		AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN	|
		AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY	|
		AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE	|
		AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT,
		0u,		// Stride in pixels, ignored for AHardwareBuffer_allocate()
		0u,		// Initialize to zero, reserved for future use
		0u		// Initialize to zero, reserved for future use
	};

	// If we have AHardwareBuffer_isSupported use that before trying the allocation.
	if (ahbFunctions.isSupported != DE_NULL)
	{
		if (!ahbFunctions.isSupported(&hbufferdesc))
			TCU_THROW(NotSupportedError, "Texture format unsupported");
	}

	if (ahbFunctions.allocate(&hbufferdesc, &m_hardwareBuffer) != 0)
	{
		// Throw unsupported instead of failing the test as the texture format or the number
		// of layers might be unsupported.
		TCU_THROW(NotSupportedError, "AHB allocation failed");
	}
}

AndroidNativeClientBuffer::~AndroidNativeClientBuffer (void)
{
	ahbFunctions.release(m_hardwareBuffer);
}

EGLClientBuffer AndroidNativeClientBuffer::get (void) const
{
	typedef EGLW_APICALL EGLClientBuffer (EGLW_APIENTRY* eglGetNativeClientBufferANDROIDFunc) (const struct AHardwareBuffer *buffer);
	return ((eglGetNativeClientBufferANDROIDFunc)m_egl.getProcAddress("eglGetNativeClientBufferANDROID"))(m_hardwareBuffer);
}

void AndroidNativeClientBuffer::lock (void** data)
{
	const int status = AHardwareBuffer_lock(m_hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1, DE_NULL, data);

	if (status != 0)
		TCU_FAIL(("AHardwareBuffer_lock failed with error: " + de::toString(status)).c_str());
}

void AndroidNativeClientBuffer::unlock (void)
{
	const int status = AHardwareBuffer_unlock(m_hardwareBuffer, DE_NULL);

	if (status != 0)
		TCU_FAIL(("AHardwareBuffer_unlock failed with error: " + de::toString(status)).c_str());
}

AHardwareBuffer_Desc AndroidNativeClientBuffer::describe (void)
{
	AHardwareBuffer_Desc ret;
	ahbFunctions.describe(m_hardwareBuffer, &ret);
	return ret;
}

class AndroidNativeImageSource : public ImageSource
{
public:
							AndroidNativeImageSource	(GLenum format, deUint32 numLayers, bool isYUV) : m_format(format), m_numLayers(numLayers), m_isY8Cb8Cr8_420(isYUV) {}
							~AndroidNativeImageSource	(void);
	MovePtr<ClientBuffer>	createBuffer				(const Library& egl, const glw::Functions&, Texture2D*) const;
	string					getRequiredExtension		(void) const { return "EGL_ANDROID_get_native_client_buffer"; }
	EGLImageKHR				createImage					(const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;
	GLenum					getEffectiveFormat			(void) const { return m_format; }
	bool					isYUVFormatImage			(void) const { return m_isY8Cb8Cr8_420;	}
protected:
	GLenum					m_format;
	deUint32				m_numLayers;
	bool					m_isY8Cb8Cr8_420;
};

AndroidNativeImageSource::~AndroidNativeImageSource (void)
{
}

MovePtr<ClientBuffer> AndroidNativeImageSource::createBuffer (const Library& egl, const glw::Functions&, Texture2D* ref) const
{
	MovePtr<AndroidNativeClientBuffer> buffer (new AndroidNativeClientBuffer(egl, m_format, m_numLayers, m_isY8Cb8Cr8_420));

	if (ref != DE_NULL)
	{
		const TextureFormat	texFormat	= glu::mapGLInternalFormat(m_format);
		void*				bufferData	= DE_NULL;

		*ref = Texture2D(texFormat, 64, 64);
		ref->m_yuvTextureUsed = m_isY8Cb8Cr8_420;
		ref->allocLevel(0);
		tcu::fillWithComponentGradients(ref->getLevel(0),
										tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
										tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));

		// AHB doesn't allow locking a layered image. In that case the data
		// will be initialized later using OpenGL API.
		// YUV format texture will be initialized by glClear.

		if (m_numLayers == 1u && !m_isY8Cb8Cr8_420)
		{
			buffer->lock(&bufferData);
			{
				AHardwareBuffer_Desc	desc			= buffer->describe();
				const int				rowPitch		= texFormat.getPixelSize() * desc.stride;
				const int				slicePitch		= rowPitch * desc.height;
				PixelBufferAccess		nativeBuffer	(texFormat, desc.width, desc.height, 1, rowPitch, slicePitch, bufferData);

				tcu::copy(nativeBuffer, ref->getLevel(0));
			}
			buffer->unlock();
		}
	}
	return MovePtr<ClientBuffer>(buffer);
}

EGLImageKHR AndroidNativeImageSource::createImage (const Library& egl, EGLDisplay dpy, EGLContext, EGLClientBuffer clientBuffer) const
{
	static const EGLint	attribs[]	= { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
	const EGLImageKHR	image		= egl.createImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attribs);

	EGLU_CHECK_MSG(egl, "eglCreateImageKHR()");
	return image;
}

} // anonymous

MovePtr<ImageSource> createAndroidNativeImageSource	(GLenum format, deUint32 numLayers, bool isYUV)
{
	try
	{
		return MovePtr<ImageSource>(new AndroidNativeImageSource(format, numLayers, isYUV));
	}
	catch (const std::runtime_error& exc)
	{
		return createUnsupportedImageSource(string("Android native buffers unsupported: ") + exc.what(), format, isYUV);
	}
}

#endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)

#endif // DE_OS == DE_OS_ANDROID

} // Image
} // egl
} // deqp
