/*-------------------------------------------------------------------------
 * 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"

#if (DE_OS == DE_OS_ANDROID)
#	include "tcuAndroidInternals.hpp"
#endif

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)
{
	return createUnsupportedImageSource("Not Android platform");
}

#else // DE_OS == DE_OS_ANDROID

using tcu::Android::internal::LibUI;
using tcu::Android::internal::GraphicBuffer;
using tcu::Android::internal::PixelFormat;
using tcu::Android::internal::status_t;

PixelFormat getPixelFormat (GLenum format)
{
	switch (format)
	{
		case GL_RGB565:		return tcu::Android::internal::PIXEL_FORMAT_RGB_565;
		case GL_RGB8:		return tcu::Android::internal::PIXEL_FORMAT_RGB_888;
		case GL_RGBA4:		return tcu::Android::internal::PIXEL_FORMAT_RGBA_4444;
		case GL_RGB5_A1:	return tcu::Android::internal::PIXEL_FORMAT_RGBA_5551;
		case GL_RGBA8:		return tcu::Android::internal::PIXEL_FORMAT_RGBA_8888;
		default:			TCU_THROW(NotSupportedError, "Texture format unsupported by Android");
	}
}

class AndroidNativeClientBuffer : public ClientBuffer
{
public:
							AndroidNativeClientBuffer	(const LibUI& lib, GLenum format);
	EGLClientBuffer			get							(void) const { return reinterpret_cast<EGLClientBuffer>(m_windowBuffer); }
	GraphicBuffer&			getGraphicBuffer			(void) { return m_graphicBuffer; }

private:
	GraphicBuffer			m_graphicBuffer;
	ANativeWindowBuffer*	m_windowBuffer;
};

AndroidNativeClientBuffer::AndroidNativeClientBuffer (const LibUI& lib, GLenum format)
	: m_graphicBuffer	(lib, 64, 64, getPixelFormat(format),
						 GraphicBuffer::USAGE_SW_READ_OFTEN		|
						 GraphicBuffer::USAGE_SW_WRITE_RARELY	|
						 GraphicBuffer::USAGE_HW_TEXTURE		|
						 GraphicBuffer::USAGE_HW_RENDER)
	, m_windowBuffer	(m_graphicBuffer.getNativeBuffer())
{
}

class AndroidNativeImageSource : public ImageSource
{
public:
							AndroidNativeImageSource	(GLenum format) : m_format(format) {}
	MovePtr<ClientBuffer>	createBuffer 				(const glw::Functions&, Texture2D*) const;
	string					getRequiredExtension		(void) const { return "EGL_ANDROID_image_native_buffer"; }
	EGLImageKHR				createImage					(const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;

protected:
	GLenum					m_format;
	LibUI					m_libui;
};

void checkStatus (status_t status)
{
	if (status != tcu::Android::internal::OK)
		TCU_FAIL(("Android error: status code " + de::toString(status)).c_str());
}

MovePtr<ClientBuffer> AndroidNativeImageSource::createBuffer (const glw::Functions&, Texture2D* ref) const
{
	MovePtr<AndroidNativeClientBuffer>	buffer			(new AndroidNativeClientBuffer(m_libui, m_format));
	GraphicBuffer&						graphicBuffer	= buffer->getGraphicBuffer();
	if (ref != DE_NULL)
	{
		const TextureFormat	texFormat	= glu::mapGLInternalFormat(m_format);
		void*				bufferData	= DE_NULL;

		*ref = Texture2D(texFormat, 64, 64);
		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));
		checkStatus(graphicBuffer.lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, &bufferData));
		{
			PixelBufferAccess nativeBuffer(texFormat, 64, 64, 1, bufferData);
			tcu::copy(nativeBuffer, ref->getLevel(0));
		}
		checkStatus(graphicBuffer.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;
}

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

#endif // DE_OS == DE_OS_ANDROID

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