/*-------------------------------------------------------------------------
 * 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 Common utilities for EGL images.
 *//*--------------------------------------------------------------------*/


#include "teglImageUtil.hpp"

#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"

#include "egluGLUtil.hpp"
#include "egluNativeWindow.hpp"
#include "egluNativePixmap.hpp"

#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"

#include "glwEnums.hpp"

#include "gluObjectWrapper.hpp"
#include "gluTextureUtil.hpp"

namespace deqp
{
namespace egl
{
namespace Image
{

using std::string;
using std::vector;

using de::UniquePtr;
using de::MovePtr;

using tcu::TextureFormat;
using tcu::Texture2D;
using tcu::Vec4;

using glu::Framebuffer;
using glu::Texture;

using eglu::AttribMap;
using eglu::UniqueSurface;
using eglu::NativeDisplay;
using eglu::NativeWindow;
using eglu::NativePixmap;
using eglu::NativeDisplayFactory;
using eglu::NativeWindowFactory;
using eglu::NativePixmapFactory;
using eglu::WindowParams;

using namespace glw;
using namespace eglw;

enum {
	IMAGE_WIDTH		= 64,
	IMAGE_HEIGHT	= 64,
};


template <typename T>
struct NativeSurface : public ManagedSurface
{
public:
	explicit		NativeSurface	(MovePtr<UniqueSurface>	surface,
									 MovePtr<T>				native)
						: ManagedSurface	(surface)
						, m_native			(native) {}

private:
	UniquePtr<T>	m_native;
};

typedef NativeSurface<NativeWindow> NativeWindowSurface;
typedef NativeSurface<NativePixmap> NativePixmapSurface;

MovePtr<ManagedSurface> createSurface (EglTestContext& eglTestCtx, EGLDisplay dpy, EGLConfig config, int width, int height)
{
	const Library&				egl				= eglTestCtx.getLibrary();
	EGLint						surfaceTypeBits	= eglu::getConfigAttribInt(egl, dpy, config, EGL_SURFACE_TYPE);
	const NativeDisplayFactory&	displayFactory	= eglTestCtx.getNativeDisplayFactory();
	NativeDisplay&				nativeDisplay	= eglTestCtx.getNativeDisplay();

	if (surfaceTypeBits & EGL_PBUFFER_BIT)
	{
		static const EGLint attribs[]	= { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE };
		const EGLSurface	surface		= egl.createPbufferSurface(dpy, config, attribs);

		EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()");

		return de::newMovePtr<ManagedSurface>(MovePtr<UniqueSurface>(new UniqueSurface(egl, dpy, surface)));
	}
	else if (surfaceTypeBits & EGL_WINDOW_BIT)
	{
		const NativeWindowFactory&	windowFactory	= selectNativeWindowFactory(displayFactory, eglTestCtx.getTestContext().getCommandLine());

		MovePtr<NativeWindow>		window	(windowFactory.createWindow(&nativeDisplay, dpy, config, DE_NULL, WindowParams(width, height, WindowParams::VISIBILITY_DONT_CARE)));
		const EGLSurface			surface	= eglu::createWindowSurface(nativeDisplay, *window, dpy, config, DE_NULL);

		return MovePtr<ManagedSurface>(new NativeWindowSurface(MovePtr<UniqueSurface>(new UniqueSurface(egl, dpy, surface)), window));
	}
	else if (surfaceTypeBits & EGL_PIXMAP_BIT)
	{
		const NativePixmapFactory&	pixmapFactory	= selectNativePixmapFactory(displayFactory, eglTestCtx.getTestContext().getCommandLine());

		MovePtr<NativePixmap>	pixmap	(pixmapFactory.createPixmap(&nativeDisplay, dpy, config, DE_NULL, width, height));
		const EGLSurface		surface	= eglu::createPixmapSurface(eglTestCtx.getNativeDisplay(), *pixmap, dpy, config, DE_NULL);

		return MovePtr<ManagedSurface>(new NativePixmapSurface(MovePtr<UniqueSurface>(new UniqueSurface(egl, dpy, surface)), pixmap));
	}
	else
		TCU_FAIL("No valid surface types supported in config");
}

class GLClientBuffer : public ClientBuffer
{
	EGLClientBuffer	get		(void) const { return reinterpret_cast<EGLClientBuffer>(static_cast<deUintptr>(getName())); }

protected:
	virtual GLuint	getName	(void) const = 0;
};

class TextureClientBuffer : public GLClientBuffer
{
public:
						TextureClientBuffer	(const glw::Functions& gl) : m_texture (gl) {}
	GLuint				getName				(void) const { return *m_texture; }

private:
	glu::Texture		m_texture;
};

class GLImageSource : public ImageSource
{
public:
	EGLImageKHR			createImage			(const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;

protected:
	virtual AttribMap	getCreateAttribs	(void) const = 0;
	virtual EGLenum		getSource			(void) const = 0;
};

EGLImageKHR GLImageSource::createImage (const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const
{
	AttribMap				attribMap	= getCreateAttribs();

	attribMap[EGL_IMAGE_PRESERVED_KHR] = EGL_TRUE;

	{
		const vector<EGLint> 	attribs	= eglu::attribMapToList(attribMap);
		const EGLImageKHR		image 	= egl.createImageKHR(dpy, ctx, getSource(),
															 clientBuffer, &attribs.front());
		EGLU_CHECK_MSG(egl, "eglCreateImageKHR()");
		return image;
	}
}

class TextureImageSource : public GLImageSource
{
public:
							TextureImageSource	(GLenum format, GLenum type, bool useTexLevel0) : m_format(format), m_type(type), m_useTexLevel0(useTexLevel0) {}
	MovePtr<ClientBuffer>	createBuffer		(const glw::Functions& gl, Texture2D* reference) const;
	GLenum					getFormat			(void) const { return m_format; }

protected:
	AttribMap				getCreateAttribs	(void) const;
	virtual void			initTexture			(const glw::Functions& gl) const = 0;
	virtual GLenum			getGLTarget			(void) const = 0;

	GLenum					m_format;
	GLenum					m_type;
	bool					m_useTexLevel0;
};

AttribMap TextureImageSource::getCreateAttribs (void) const
{
	AttribMap ret;

	ret[EGL_GL_TEXTURE_LEVEL_KHR] = 0;

	return ret;
}

MovePtr<ClientBuffer> TextureImageSource::createBuffer (const glw::Functions& gl, Texture2D* ref) const
{
	MovePtr<TextureClientBuffer>	clientBuffer	(new TextureClientBuffer(gl));
	const GLuint					texture			= clientBuffer->getName();
	const GLenum					target			= getGLTarget();

	GLU_CHECK_GLW_CALL(gl, bindTexture(target, texture));
	initTexture(gl);

	if (!m_useTexLevel0)
	{
		// Set minification filter to linear. This makes the texture complete.
		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
	}

	if (ref != DE_NULL)
	{
		GLenum		imgTarget	= eglu::getImageGLTarget(getSource());

		*ref = Texture2D(glu::mapGLTransferFormat(m_format, m_type), IMAGE_WIDTH, IMAGE_HEIGHT);
		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));

		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
		GLU_CHECK_GLW_CALL(gl, texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));

		GLU_CHECK_GLW_CALL(gl, texImage2D(imgTarget, 0, m_format, IMAGE_WIDTH, IMAGE_HEIGHT,
										  0, m_format, m_type, ref->getLevel(0).getDataPtr()));
	}
	GLU_CHECK_GLW_CALL(gl, bindTexture(target, 0));
	return MovePtr<ClientBuffer>(clientBuffer);
}

class Texture2DImageSource : public TextureImageSource
{
public:
					Texture2DImageSource	(GLenum format, GLenum type, bool useTexLevel0) : TextureImageSource(format, type, useTexLevel0) {}
	EGLenum			getSource				(void) const { return EGL_GL_TEXTURE_2D_KHR; }
	string			getRequiredExtension	(void) const { return "EGL_KHR_gl_texture_2D_image"; }
	GLenum			getGLTarget				(void) const { return GL_TEXTURE_2D; }

protected:
	void			initTexture				(const glw::Functions& gl) const;
};

void Texture2DImageSource::initTexture (const glw::Functions& gl) const
{
	// Specify mipmap level 0
	GLU_CHECK_CALL_ERROR(gl.texImage2D(GL_TEXTURE_2D, 0, m_format, IMAGE_WIDTH, IMAGE_HEIGHT, 0, m_format, m_type, DE_NULL),
						 gl.getError());
}

class TextureCubeMapImageSource : public TextureImageSource
{
public:
					TextureCubeMapImageSource	(EGLenum source, GLenum format, GLenum type, bool useTexLevel0) : TextureImageSource(format, type, useTexLevel0), m_source(source) {}
	EGLenum			getSource					(void) const { return m_source; }
	string			getRequiredExtension		(void) const { return "EGL_KHR_gl_texture_cubemap_image"; }
	GLenum			getGLTarget					(void) const { return GL_TEXTURE_CUBE_MAP; }

protected:
	void			initTexture					(const glw::Functions& gl) const;

	EGLenum			m_source;
};

void TextureCubeMapImageSource::initTexture (const glw::Functions& gl) const
{
	// Specify mipmap level 0 for all faces
	static const GLenum faces[] =
	{
		GL_TEXTURE_CUBE_MAP_POSITIVE_X,
		GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
		GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
		GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
	};

	for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); faceNdx++)
		GLU_CHECK_GLW_CALL(gl, texImage2D(faces[faceNdx], 0, m_format, IMAGE_WIDTH, IMAGE_HEIGHT, 0, m_format, m_type, DE_NULL));
}

class RenderbufferClientBuffer : public GLClientBuffer
{
public:
						RenderbufferClientBuffer	(const glw::Functions& gl) : m_rbo (gl) {}
	GLuint				getName						(void) const { return *m_rbo; }

private:
	glu::Renderbuffer	m_rbo;
};

class RenderbufferImageSource : public GLImageSource
{
public:
							RenderbufferImageSource	(GLenum format) : m_format(format) {}

	string					getRequiredExtension	(void) const 	{ return "EGL_KHR_gl_renderbuffer_image"; }
	MovePtr<ClientBuffer>	createBuffer			(const glw::Functions& gl, Texture2D* reference) const;
	GLenum					getFormat				(void) const { return m_format; }

protected:
	EGLenum					getSource				(void) const	{ return EGL_GL_RENDERBUFFER_KHR; }
	AttribMap				getCreateAttribs		(void) const	{ return AttribMap(); }

	GLenum					m_format;
};

void initializeStencilRbo(const glw::Functions& gl, GLuint rbo, Texture2D& ref)
{
	static const deUint32 stencilValues[] =
	{
		0xBF688C11u,
		0xB43D2922u,
		0x055D5FFBu,
		0x9300655Eu,
		0x63BE0DF2u,
		0x0345C13Bu,
		0x1C184832u,
		0xD107040Fu,
		0x9B91569Fu,
		0x0F0CFDC7u,
	};

	const deUint32 numStencilBits	= tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(ref.getLevel(0).getFormat(), tcu::Sampler::MODE_STENCIL)).x();
	const deUint32 stencilMask		= deBitMask32(0, numStencilBits);

	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
												   GL_RENDERBUFFER, rbo));
	GLU_CHECK_GLW_CALL(gl, clearStencil(0));
	GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));
	tcu::clearStencil(ref.getLevel(0), 0);

	// create a pattern
	GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stencilValues); ++ndx)
	{
		const deUint32		stencil	= stencilValues[ndx] & stencilMask;
		const tcu::IVec2	size	= tcu::IVec2((int)((DE_LENGTH_OF_ARRAY(stencilValues) - ndx) * (ref.getWidth() / float(DE_LENGTH_OF_ARRAY(stencilValues)))),
												 (int)((DE_LENGTH_OF_ARRAY(stencilValues) - ndx) * (ref.getHeight() / float(DE_LENGTH_OF_ARRAY(stencilValues) + 4)))); // not symmetric

		if (size.x() == 0 || size.y() == 0)
			break;

		GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
		GLU_CHECK_GLW_CALL(gl, clearStencil(stencil));
		GLU_CHECK_GLW_CALL(gl, clear(GL_STENCIL_BUFFER_BIT));

		tcu::clearStencil(tcu::getSubregion(ref.getLevel(0), 0, 0, size.x(), size.y()), stencil);
	}

	GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
												   GL_RENDERBUFFER, 0));
}

void initializeDepthRbo(const glw::Functions& gl, GLuint rbo, Texture2D& ref)
{
	const int NUM_STEPS = 13;

	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
												   GL_RENDERBUFFER, rbo));

	GLU_CHECK_GLW_CALL(gl, clearDepthf(0.0f));
	GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));
	tcu::clearDepth(ref.getLevel(0), 0.0f);

	// create a pattern
	GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
	for (int ndx = 0; ndx < NUM_STEPS; ++ndx)
	{
		const float			depth	= ndx / float(NUM_STEPS);
		const tcu::IVec2	size	= tcu::IVec2((int)((NUM_STEPS - ndx) * (ref.getWidth() / float(NUM_STEPS))),
												 (int)((NUM_STEPS - ndx) * (ref.getHeight() / float(NUM_STEPS + 4)))); // not symmetric

		if (size.x() == 0 || size.y() == 0)
			break;

		GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
		GLU_CHECK_GLW_CALL(gl, clearDepthf(depth));
		GLU_CHECK_GLW_CALL(gl, clear(GL_DEPTH_BUFFER_BIT));

		tcu::clearDepth(tcu::getSubregion(ref.getLevel(0), 0, 0, size.x(), size.y()), depth);
	}

	GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
												   GL_RENDERBUFFER, 0));

}

void initializeColorRbo(const glw::Functions& gl, GLuint rbo, Texture2D& ref)
{
	static const tcu::Vec4 colorValues[] =
	{
		tcu::Vec4(0.9f, 0.5f, 0.65f, 1.0f),
		tcu::Vec4(0.5f, 0.7f, 0.65f, 1.0f),
		tcu::Vec4(0.2f, 0.5f, 0.65f, 1.0f),
		tcu::Vec4(0.3f, 0.1f, 0.5f, 1.0f),
		tcu::Vec4(0.8f, 0.2f, 0.3f, 1.0f),
		tcu::Vec4(0.9f, 0.4f, 0.8f, 1.0f),
	};

	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
												   GL_RENDERBUFFER, rbo));
	GLU_CHECK_GLW_CALL(gl, clearColor(1.0f, 1.0f, 0.0f, 1.0f));
	GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));
	tcu::clear(ref.getLevel(0), Vec4(1.0f, 1.0f, 0.0f, 1.0f));

	// create a pattern
	GLU_CHECK_GLW_CALL(gl, enable(GL_SCISSOR_TEST));
	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorValues); ++ndx)
	{
		const tcu::IVec2	size	= tcu::IVec2((int)((DE_LENGTH_OF_ARRAY(colorValues) - ndx) * (ref.getWidth() / float(DE_LENGTH_OF_ARRAY(colorValues)))),
												 (int)((DE_LENGTH_OF_ARRAY(colorValues) - ndx) * (ref.getHeight() / float(DE_LENGTH_OF_ARRAY(colorValues) + 4)))); // not symmetric

		if (size.x() == 0 || size.y() == 0)
			break;

		GLU_CHECK_GLW_CALL(gl, scissor(0, 0, size.x(), size.y()));
		GLU_CHECK_GLW_CALL(gl, clearColor(colorValues[ndx].x(), colorValues[ndx].y(), colorValues[ndx].z(), colorValues[ndx].w()));
		GLU_CHECK_GLW_CALL(gl, clear(GL_COLOR_BUFFER_BIT));

		tcu::clear(tcu::getSubregion(ref.getLevel(0), 0, 0, size.x(), size.y()), colorValues[ndx]);
	}

	GLU_CHECK_GLW_CALL(gl, disable(GL_SCISSOR_TEST));
	GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
												   GL_RENDERBUFFER, 0));
}

MovePtr<ClientBuffer> RenderbufferImageSource::createBuffer (const glw::Functions& gl, Texture2D* ref) const
{
	MovePtr<RenderbufferClientBuffer>	buffer	(new RenderbufferClientBuffer(gl));
	const GLuint						rbo		= buffer->getName();

	GLU_CHECK_CALL_ERROR(gl.bindRenderbuffer(GL_RENDERBUFFER, rbo), gl.getError());

	// Specify storage.
	GLU_CHECK_CALL_ERROR(gl.renderbufferStorage(GL_RENDERBUFFER, m_format, 64, 64), gl.getError());

	if (ref != DE_NULL)
	{
		Framebuffer			fbo			(gl);
		const TextureFormat	texFormat	= glu::mapGLInternalFormat(m_format);

		*ref = tcu::Texture2D(texFormat, 64, 64);
		ref->allocLevel(0);

		gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo);
		switch (m_format)
		{
			case GL_STENCIL_INDEX8:
				initializeStencilRbo(gl, rbo, *ref);
				break;
			case GL_DEPTH_COMPONENT16:
				initializeDepthRbo(gl, rbo, *ref);
				break;
			case GL_RGBA4:
				initializeColorRbo(gl, rbo, *ref);
				break;
			case GL_RGB5_A1:
				initializeColorRbo(gl, rbo, *ref);
				break;
			case GL_RGB565:
				initializeColorRbo(gl, rbo, *ref);
				break;
			default:
				DE_ASSERT(!"Impossible");
		}

		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
	}

	return MovePtr<ClientBuffer>(buffer);
}

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

private:
	const string			m_message;
	GLenum					m_format;

	void					fail					(void) const { TCU_THROW(NotSupportedError, m_message.c_str()); }
};

EGLImageKHR	UnsupportedImageSource::createImage (const Library&, EGLDisplay, EGLContext, EGLClientBuffer) const
{
	fail();
	return EGL_NO_IMAGE_KHR;
}

MovePtr<ImageSource> createTextureImageSource (EGLenum source, GLenum format, GLenum type, bool useTexLevel0)
{
	if (source == EGL_GL_TEXTURE_2D_KHR)
		return MovePtr<ImageSource>(new Texture2DImageSource(format, type, useTexLevel0));
	else
		return MovePtr<ImageSource>(new TextureCubeMapImageSource(source, format, type, useTexLevel0));
}

MovePtr<ImageSource> createRenderbufferImageSource (GLenum format)
{
	return MovePtr<ImageSource>(new RenderbufferImageSource(format));
}

MovePtr<ImageSource> createUnsupportedImageSource (const string& message, GLenum format)
{
	return MovePtr<ImageSource>(new UnsupportedImageSource(message, format));
}

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