/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * 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 Platform that uses X11 via GLX.
 *//*--------------------------------------------------------------------*/

#include "tcuX11GlxPlatform.hpp"
#include "tcuX11Platform.hpp"

#include "tcuRenderTarget.hpp"
#include "glwInitFunctions.hpp"
#include "deUniquePtr.hpp"

#include <sstream>
#include <iterator>
#include <set>

#define GLX_GLXEXT_PROTOTYPES
#include <GL/glx.h>

namespace tcu
{
namespace x11
{
namespace glx
{

using de::UniquePtr;
using de::MovePtr;
using glu::ApiType;
using glu::ContextFactory;
using glu::ContextType;
using glu::RenderConfig;
using glu::RenderContext;
using tcu::CommandLine;
using tcu::RenderTarget;
using std::string;
using std::set;
using std::istringstream;
using std::ostringstream;
using std::istream_iterator;

typedef RenderConfig::Visibility Visibility;


template<typename T>
static inline T checkGLX(T value, const char* expr, const char* file, int line)
{
	if (!value)
		throw tcu::TestError("GLX call failed", expr, file, line);
	return value;
}

#define TCU_CHECK_GLX(EXPR) checkGLX(EXPR, #EXPR, __FILE__, __LINE__)
#define TCU_CHECK_GLX_CONFIG(EXPR) checkGLX((EXPR) == Success, #EXPR, __FILE__, __LINE__)

class GlxContextFactory : public glu::ContextFactory
{
public:
							GlxContextFactory	(EventState& eventState);
							~GlxContextFactory	(void);
	RenderContext*			createContext		(const RenderConfig&	config,
												 const CommandLine&		cmdLine) const;

	EventState&				getEventState		(void) const { return m_eventState;}

	const PFNGLXCREATECONTEXTATTRIBSARBPROC
							m_glXCreateContextAttribsARB;

private:
	EventState&				m_eventState;
};

class GlxDisplay : public XlibDisplay
{
public:
							GlxDisplay				(EventState&	eventState,
													 const char*	name);
	int						getGlxMajorVersion		(void) const { return m_majorVersion; }
	int						getGlxMinorVersion		(void) const { return m_minorVersion; }
	bool					isGlxExtensionSupported (const char* extName) const;

private:
	int						m_errorBase;
	int						m_eventBase;
	int						m_majorVersion;
	int						m_minorVersion;
	set<string>				m_extensions;
};

class GlxVisual
{
public:
							GlxVisual			(GlxDisplay& display, GLXFBConfig fbConfig);
	int						getAttrib			(int attribute);
	Visual*					getXVisual			(void) { return m_visual; }
	GLXContext				createContext		(const GlxContextFactory&	factory,
												 const ContextType&			contextType);
	GLXWindow				createWindow		(::Window xWindow);
	GlxDisplay&				getGlxDisplay		(void) { return m_display; }
	::Display*				getXDisplay			(void) { return m_display.getXDisplay(); }

private:
	GlxDisplay&				m_display;
	::Visual*				m_visual;
	const GLXFBConfig		m_fbConfig;
};

class GlxDrawable
{
public:
	virtual					~GlxDrawable		(void) {}

	virtual void			processEvents		(void) {}
	virtual void			getDimensions		(int* width, int* height) = 0;
	int						getWidth			(void);
	int						getHeight			(void);
	void					swapBuffers			(void) { glXSwapBuffers(getXDisplay(), getGLXDrawable()); }

	virtual ::Display*		getXDisplay			(void) = 0;
	virtual GLXDrawable		getGLXDrawable		(void) = 0;

protected:
							GlxDrawable			() {}
	unsigned int			getAttrib			(int attribute);
};

class GlxWindow : public GlxDrawable
{
public:
							GlxWindow			(GlxVisual& visual, const RenderConfig& cfg);
							~GlxWindow			(void);
	void					processEvents		(void) { m_x11Window.processEvents(); }
	::Display*				getXDisplay			(void) { return m_x11Display.getXDisplay(); }
	void					getDimensions		(int* width, int* height);

protected:
	GLXDrawable				getGLXDrawable		() { return m_GLXDrawable; }

private:
	XlibDisplay&			m_x11Display;
	XlibWindow				m_x11Window;
	const GLXDrawable		m_GLXDrawable;
};

class GlxRenderContext : public RenderContext
{
public:
										GlxRenderContext	(const GlxContextFactory&	factory,
															 const RenderConfig&		config);
										~GlxRenderContext	(void);
	virtual ContextType					getType				(void) const;
	virtual void						postIterate			(void);
	void								makeCurrent			(void);
	void								clearCurrent		(void);
	virtual const glw::Functions&		getFunctions		(void) const;
	virtual const tcu::RenderTarget&	getRenderTarget		(void) const;

private:
	GlxDisplay							m_glxDisplay;
	GlxVisual							m_glxVisual;
	ContextType							m_type;
	GLXContext							m_GLXContext;
	UniquePtr<GlxDrawable>				m_glxDrawable;
	RenderTarget						m_renderTarget;
	glw::Functions						m_functions;
};

extern "C"
{
	static int tcuX11GlxErrorHandler (::Display* display, XErrorEvent* event)
	{
		char buf[80];
		XGetErrorText(display, event->error_code, buf, sizeof(buf));
		tcu::print("X operation %u:%u failed: %s\n",
				   event->request_code, event->minor_code, buf);
		return 0;
	}
}

GlxContextFactory::GlxContextFactory (EventState& eventState)
	: glu::ContextFactory			("glx", "X11 GLX OpenGL Context")
	, m_glXCreateContextAttribsARB	(
		reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(
			TCU_CHECK_GLX(
				glXGetProcAddress(
					reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB")))))
	, m_eventState					(eventState)
{
	XSetErrorHandler(tcuX11GlxErrorHandler);
}

RenderContext* GlxContextFactory::createContext (const RenderConfig&	config,
												 const CommandLine&		cmdLine) const
{
	DE_UNREF(cmdLine);
	GlxRenderContext* const renderContext = new GlxRenderContext(*this, config);
	return renderContext;
}

GlxContextFactory::~GlxContextFactory (void)
{
}

GlxDisplay::GlxDisplay (EventState& eventState, const char* name)
	: XlibDisplay	(eventState, name)
{
	const Bool supported = glXQueryExtension(m_display, &m_errorBase, &m_eventBase);
	if (!supported)
		TCU_THROW(NotSupportedError, "GLX protocol not supported by X server");

	TCU_CHECK_GLX(glXQueryVersion(m_display, &m_majorVersion, &m_minorVersion));

	{
		const int screen = XDefaultScreen(m_display);
		// nVidia doesn't seem to report client-side extensions correctly,
		// so only use server side
		const char* const extensions =
			TCU_CHECK_GLX(glXQueryServerString(m_display, screen, GLX_EXTENSIONS));
		istringstream extStream(extensions);
		m_extensions = set<string>(istream_iterator<string>(extStream),
								   istream_iterator<string>());
	}
}


bool GlxDisplay::isGlxExtensionSupported (const char* extName) const
{
	return m_extensions.find(extName) != m_extensions.end();
}

//! Throw `tcu::NotSupportedError` if `dpy` is not compatible with GLX
//! version `major`.`minor`.
static void checkGlxVersion (const GlxDisplay& dpy, int major, int minor)
{
	const int dpyMajor = dpy.getGlxMajorVersion();
	const int dpyMinor = dpy.getGlxMinorVersion();
	if (!(dpyMajor == major && dpyMinor >= minor))
	{
		ostringstream oss;
		oss << "Server GLX version "
			<< dpyMajor << "." << dpyMinor
			<< " not compatible with required version "
			<< major << "." << minor;
		TCU_THROW(NotSupportedError, oss.str().c_str());
	}
}

//! Throw `tcu::NotSupportedError` if `dpy` does not support extension `extName`.
static void checkGlxExtension (const GlxDisplay& dpy, const char* extName)
{
	if (!dpy.isGlxExtensionSupported(extName))
	{
		ostringstream oss;
		oss << "GLX extension \"" << extName << "\" not supported";
		TCU_THROW(NotSupportedError, oss.str().c_str());
	}
}

GlxVisual::GlxVisual (GlxDisplay& display, GLXFBConfig fbConfig)
	: m_display		(display)
	, m_visual		(DE_NULL)
	, m_fbConfig	(fbConfig)
{
	XVisualInfo* visualInfo = glXGetVisualFromFBConfig(getXDisplay(), fbConfig);
	if (visualInfo != DE_NULL)
	{
		m_visual = visualInfo->visual;
		XFree(visualInfo);
	}
}

int GlxVisual::getAttrib (int attribute)
{
	int fbvalue;
	TCU_CHECK_GLX_CONFIG(glXGetFBConfigAttrib(getXDisplay(), m_fbConfig, attribute, &fbvalue));
	return fbvalue;
}

GLXContext GlxVisual::createContext (const GlxContextFactory&	factory,
									 const ContextType&			contextType)
{
	int				profileMask	= 0;
	const ApiType	apiType		= contextType.getAPI();

	checkGlxVersion(m_display, 1, 4);
	checkGlxExtension(m_display, "GLX_ARB_create_context");
	checkGlxExtension(m_display, "GLX_ARB_create_context_profile");

	switch (apiType.getProfile())
	{
		case glu::PROFILE_ES:
			checkGlxExtension(m_display, "GLX_EXT_create_context_es2_profile");
			profileMask = GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
			break;
		case glu::PROFILE_CORE:
			profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
			break;
		case glu::PROFILE_COMPATIBILITY:
			profileMask = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
			break;
		default:
			DE_FATAL("Impossible context profile");
	}

	const int attribs[] =
	{
		GLX_CONTEXT_MAJOR_VERSION_ARB,	apiType.getMajorVersion(),
		GLX_CONTEXT_MINOR_VERSION_ARB,	apiType.getMinorVersion(),
		GLX_CONTEXT_FLAGS_ARB,			0,
		GLX_CONTEXT_PROFILE_MASK_ARB,	profileMask,
		None
	};
	return TCU_CHECK_GLX(factory.m_glXCreateContextAttribsARB(
							 getXDisplay(), m_fbConfig, DE_NULL, True, attribs));
}

GLXWindow GlxVisual::createWindow (::Window xWindow)
{
	return TCU_CHECK_GLX(glXCreateWindow(getXDisplay(), m_fbConfig, xWindow, NULL));
}

unsigned GlxDrawable::getAttrib (int attrib)
{
	unsigned int value = 0;
	glXQueryDrawable(getXDisplay(), getGLXDrawable(), attrib, &value);
	return value;
}

int GlxDrawable::getWidth (void)
{
	int width = 0;
	getDimensions(&width, DE_NULL);
	return width;
}

int GlxDrawable::getHeight (void)
{
	int height = 0;
	getDimensions(DE_NULL, &height);
	return height;
}

GlxWindow::GlxWindow (GlxVisual& visual, const RenderConfig& cfg)
	: m_x11Display	(visual.getGlxDisplay())
	, m_x11Window	(m_x11Display, cfg.width, cfg.height,
					 visual.getXVisual())
	, m_GLXDrawable	(visual.createWindow(m_x11Window.getXID()))
{
	m_x11Window.setVisibility(cfg.windowVisibility != RenderConfig::VISIBILITY_HIDDEN);
}

void GlxWindow::getDimensions (int* width, int* height)
{
	if (width != DE_NULL)
		*width = getAttrib(GLX_WIDTH);
	if (height != DE_NULL)
		*height = getAttrib(GLX_HEIGHT);

	// glXQueryDrawable may be buggy, so fall back to X geometry if needed
	if ((width != DE_NULL && *width == 0) || (height != DE_NULL && *height == 0))
		m_x11Window.getDimensions(width, height);
}

GlxWindow::~GlxWindow (void)
{
	glXDestroyWindow(m_x11Display.getXDisplay(), m_GLXDrawable);
}

static const struct Attribute
{
	int						glxAttribute;
	int	RenderConfig::*		cfgMember;
} s_attribs[] =
{
	{ GLX_RED_SIZE,		&RenderConfig::redBits		},
	{ GLX_GREEN_SIZE,	&RenderConfig::greenBits	},
	{ GLX_BLUE_SIZE,	&RenderConfig::blueBits		},
	{ GLX_ALPHA_SIZE,	&RenderConfig::alphaBits	},
	{ GLX_DEPTH_SIZE,	&RenderConfig::depthBits	},
	{ GLX_STENCIL_SIZE,	&RenderConfig::stencilBits	},
	{ GLX_SAMPLES,		&RenderConfig::numSamples	},
	{ GLX_FBCONFIG_ID,	&RenderConfig::id			},
};

static deUint32 surfaceTypeToDrawableBits (RenderConfig::SurfaceType type)
{
	switch (type)
	{
		case RenderConfig::SURFACETYPE_WINDOW:
			return GLX_WINDOW_BIT;
		case RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:
			return GLX_PIXMAP_BIT;
		case RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:
			return GLX_PBUFFER_BIT;
		case RenderConfig::SURFACETYPE_DONT_CARE:
			return GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
		default:
			DE_FATAL("Impossible case");
	}
	return 0;
}

static bool configMatches (GlxVisual& visual, const RenderConfig& renderCfg)
{
	if (renderCfg.id != RenderConfig::DONT_CARE)
		return visual.getAttrib(GLX_FBCONFIG_ID) == renderCfg.id;

	for (const Attribute* it = DE_ARRAY_BEGIN(s_attribs); it != DE_ARRAY_END(s_attribs); it++)
	{
		const int requested = renderCfg.*it->cfgMember;
		if (requested != RenderConfig::DONT_CARE &&
			requested != visual.getAttrib(it->glxAttribute))
			return false;
	}

	{
		deUint32 bits = surfaceTypeToDrawableBits(renderCfg.surfaceType);

		if ((visual.getAttrib(GLX_DRAWABLE_TYPE) & bits) == 0)
			return false;

		// It shouldn't be possible to have GLX_WINDOW_BIT set without a visual,
		// but let's make sure.
		if (renderCfg.surfaceType == RenderConfig::SURFACETYPE_WINDOW &&
			visual.getXVisual() == DE_NULL)
			return false;
	}

	return true;
}

class Rank
{
public:
				Rank		(void) : m_value(0), m_bitsLeft(64) {}
	void		add			(size_t bits, deUint32 value);
	void		sub			(size_t bits, deUint32 value);
	deUint64	getValue	(void) { return m_value; }

private:
	deUint64	m_value;
	size_t		m_bitsLeft;
};

void Rank::add (size_t bits, deUint32 value)
{
	TCU_CHECK_INTERNAL(m_bitsLeft >= bits);
	m_bitsLeft -= bits;
	m_value = m_value << bits | de::min((1U << bits) - 1, value);
}

void Rank::sub (size_t bits, deUint32 value)
{
	TCU_CHECK_INTERNAL(m_bitsLeft >= bits);
	m_bitsLeft -= bits;
	m_value = m_value << bits | ((1U << bits) - 1 - de::min((1U << bits) - 1U, value));
}

static deUint64 configRank (GlxVisual& visual)
{
	// Sanity checks.
	if (visual.getAttrib(GLX_DOUBLEBUFFER)					== False	||
		(visual.getAttrib(GLX_RENDER_TYPE) & GLX_RGBA_BIT)	== 0)
		return 0;

	Rank rank;
	int caveat		= visual.getAttrib(GLX_CONFIG_CAVEAT);
	int redSize		= visual.getAttrib(GLX_RED_SIZE);
	int greenSize	= visual.getAttrib(GLX_GREEN_SIZE);
	int blueSize	= visual.getAttrib(GLX_BLUE_SIZE);
	int alphaSize	= visual.getAttrib(GLX_ALPHA_SIZE);
	int depthSize	= visual.getAttrib(GLX_DEPTH_SIZE);
	int stencilSize	= visual.getAttrib(GLX_STENCIL_SIZE);
	int minRGB		= de::min(redSize, de::min(greenSize, blueSize));

	// Prefer conformant configurations.
	rank.add(1, (caveat != GLX_NON_CONFORMANT_CONFIG));

	// Prefer non-transparent configurations.
	rank.add(1, visual.getAttrib(GLX_TRANSPARENT_TYPE) == GLX_NONE);

	// Avoid stereo
	rank.add(1, visual.getAttrib(GLX_STEREO) == False);

	// Avoid overlays
	rank.add(1, visual.getAttrib(GLX_LEVEL) == 0);

	// Prefer to have some alpha.
	rank.add(1, alphaSize > 0);

	// Prefer to have a depth buffer.
	rank.add(1, depthSize > 0);

	// Prefer to have a stencil buffer.
	rank.add(1, stencilSize > 0);

	// Avoid slow configurations.
	rank.add(1, (caveat != GLX_SLOW_CONFIG));

	// Prefer larger, evenly distributed color depths
	rank.add(4, de::min(minRGB, alphaSize));

	// If alpha is low, choose best RGB
	rank.add(4, minRGB);

	// Prefer larger depth and stencil buffers
	rank.add(6, deUint32(depthSize + stencilSize));

	// Avoid excessive sampling
	rank.sub(5, visual.getAttrib(GLX_SAMPLES));

	// Prefer True/DirectColor
	int visualType = visual.getAttrib(GLX_X_VISUAL_TYPE);
	rank.add(1, visualType == GLX_TRUE_COLOR || visualType == GLX_DIRECT_COLOR);

	return rank.getValue();
}

static GlxVisual chooseVisual (GlxDisplay& display, const RenderConfig& cfg)
{
	::Display*	dpy			= display.getXDisplay();
	deUint64	maxRank		= 0;
	GLXFBConfig	maxConfig	= DE_NULL;
	int			numElems	= 0;

	GLXFBConfig* const fbConfigs = glXGetFBConfigs(dpy, DefaultScreen(dpy), &numElems);
	TCU_CHECK_MSG(fbConfigs != DE_NULL, "Couldn't query framebuffer configurations");

	for (int i = 0; i < numElems; i++)
	{
		GlxVisual visual(display, fbConfigs[i]);

		if (!configMatches(visual, cfg))
			continue;

		deUint64 cfgRank = configRank(visual);

		if (cfgRank > maxRank)
		{
			maxRank		= cfgRank;
			maxConfig	= fbConfigs[i];
		}
	}
	XFree(fbConfigs);

	if (maxRank == 0)
		TCU_THROW(NotSupportedError, "Requested GLX configuration not found or unusable");

	return GlxVisual(display, maxConfig);
}

GlxDrawable* createDrawable (GlxVisual& visual, const RenderConfig& config)
{
	RenderConfig::SurfaceType surfaceType = config.surfaceType;

	if (surfaceType == RenderConfig::SURFACETYPE_DONT_CARE)
	{
		if (visual.getXVisual() == DE_NULL)
			// No visual, cannot create X window
			surfaceType = RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE;
		else
			surfaceType = RenderConfig::SURFACETYPE_WINDOW;
	}

	switch (surfaceType)
	{
		case RenderConfig::SURFACETYPE_DONT_CARE:
			DE_FATAL("Impossible case");

		case RenderConfig::SURFACETYPE_WINDOW:
			return new GlxWindow(visual, config);
			break;

		case RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:
			// \todo [2013-11-28 lauri] Pixmaps

		case RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:
			// \todo [2013-11-28 lauri] Pbuffers

		default:
			TCU_THROW(NotSupportedError, "Unsupported surface type");
	}

	return DE_NULL;
}

struct GlxFunctionLoader : public glw::FunctionLoader
{
							GlxFunctionLoader	(void) {}

	glw::GenericFuncType	get					(const char* name) const
	{
		return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
	}
};

GlxRenderContext::GlxRenderContext (const GlxContextFactory&	factory,
									const RenderConfig&			config)
	: m_glxDisplay		(factory.getEventState(), DE_NULL)
	, m_glxVisual		(chooseVisual(m_glxDisplay, config))
	, m_type			(config.type)
	, m_GLXContext		(m_glxVisual.createContext(factory, config.type))
	, m_glxDrawable		(createDrawable(m_glxVisual, config))
	, m_renderTarget	(m_glxDrawable->getWidth(), m_glxDrawable->getHeight(),
						 PixelFormat(m_glxVisual.getAttrib(GLX_RED_SIZE),
									 m_glxVisual.getAttrib(GLX_GREEN_SIZE),
									 m_glxVisual.getAttrib(GLX_BLUE_SIZE),
									 m_glxVisual.getAttrib(GLX_ALPHA_SIZE)),
						 m_glxVisual.getAttrib(GLX_DEPTH_SIZE),
						 m_glxVisual.getAttrib(GLX_STENCIL_SIZE),
						 m_glxVisual.getAttrib(GLX_SAMPLES))
{
	const GlxFunctionLoader loader;
	makeCurrent();
	glu::initFunctions(&m_functions, &loader, config.type.getAPI());
}

GlxRenderContext::~GlxRenderContext (void)
{
	clearCurrent();
	if (m_GLXContext != DE_NULL)
		glXDestroyContext(m_glxDisplay.getXDisplay(), m_GLXContext);
}

void GlxRenderContext::makeCurrent (void)
{
	const GLXDrawable drawRead = m_glxDrawable->getGLXDrawable();
	TCU_CHECK_GLX(glXMakeContextCurrent(m_glxDisplay.getXDisplay(),
										drawRead, drawRead, m_GLXContext));
}

void GlxRenderContext::clearCurrent (void)
{
	TCU_CHECK_GLX(glXMakeContextCurrent(m_glxDisplay.getXDisplay(),
										None, None, DE_NULL));
}

ContextType GlxRenderContext::getType (void) const
{
	return m_type;
}

void GlxRenderContext::postIterate (void)
{
	m_glxDrawable->swapBuffers();
	m_glxDrawable->processEvents();
	m_glxDisplay.processEvents();
}

const RenderTarget& GlxRenderContext::getRenderTarget (void) const
{
	return m_renderTarget;
}

const glw::Functions& GlxRenderContext::getFunctions (void) const
{
	return m_functions;
}

MovePtr<ContextFactory> createContextFactory (EventState& eventState)
{
	return MovePtr<ContextFactory>(new GlxContextFactory(eventState));
}

} // glx
} // x11
} // tcu
