/*-------------------------------------------------------------------------
 * 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 OS X platform.
 *//*--------------------------------------------------------------------*/

#include "tcuOSXPlatform.hpp"
#include "gluRenderContext.hpp"
#include "gluRenderConfig.hpp"
#include "tcuRenderTarget.hpp"
#include "glwFunctions.hpp"
#include "glwInitFunctions.hpp"
#include "deDynamicLibrary.hpp"
#include "glwEnums.hpp"
#include "gluDefs.hpp"

#include <string>

#include <OpenGL/OpenGL.h>
#include <OpenGL/CGLCurrent.h>
#include <OpenGL/CGLContext.h>
#include <OpenGL/CGLTypes.h>
#include <OpenGL/CGLRenderers.h>

#define OPENGL_LIBRARY_PATH "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"

namespace tcu
{

namespace
{

class GLFunctionLoader : public glw::FunctionLoader
{
public:
	GLFunctionLoader (const char* path)
		: m_library(path)
	{
	}

	glw::GenericFuncType get (const char* name) const
	{
		return m_library.getFunction(name);
	}

private:
	de::DynamicLibrary m_library;
};

} // anonymous

class CGLRenderContext : public glu::RenderContext
{
public:
								CGLRenderContext		(const glu::RenderConfig& config);
								~CGLRenderContext		(void);

	glu::ContextType			getType					(void) const { return m_type;			}
	const glw::Functions&		getFunctions			(void) const { return m_functions;		}
	const tcu::RenderTarget&	getRenderTarget			(void) const { return m_renderTarget;	}
	void						postIterate				(void) {}

private:
	const glu::ContextType		m_type;
	CGLContextObj				m_context;
	glw::Functions				m_functions;
	RenderTarget				m_renderTarget;
};

static CGLOpenGLProfile getCGLProfile (glu::ContextType type)
{
	if (type.getAPI().getProfile() != glu::PROFILE_CORE)
		throw NotSupportedError("Requested OpenGL profile is not supported in CGL");

	if (type.getAPI().getMajorVersion() == 4)
		return kCGLOGLPVersion_GL4_Core;
	else if (type.getAPI().getMajorVersion() == 3)
		return kCGLOGLPVersion_GL3_Core;
	else
		throw NotSupportedError("Requested OpenGL version is not supported in CGL");
}

static glu::ApiType getVersion (const glw::Functions& gl)
{
	int major = 0;
	int minor = 0;
	gl.getIntegerv(GL_MAJOR_VERSION, &major);
	gl.getIntegerv(GL_MINOR_VERSION, &minor);
	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to query exact GL version");
	return glu::ApiType::core(major, minor);
}

CGLRenderContext::CGLRenderContext (const glu::RenderConfig& config)
	: m_type			(config.type)
	, m_context			(DE_NULL)
	, m_renderTarget	(0, 0, tcu::PixelFormat(0,0,0,0), 0, 0, 0)
{
	try
	{
		const CGLPixelFormatAttribute attribs[] =
		{
			kCGLPFAAccelerated,
			kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)getCGLProfile(config.type),
			(CGLPixelFormatAttribute)0
		};

		CGLPixelFormatObj	pixelFormat;
		int					numVScreens;

		if (CGLChoosePixelFormat(&attribs[0], &pixelFormat, &numVScreens) != kCGLNoError)
			throw NotSupportedError("No compatible pixel formats found");

		try
		{
			if (CGLCreateContext(pixelFormat, DE_NULL, &m_context) != kCGLNoError)
				throw ResourceError("Failed to create CGL context");

			if (CGLSetCurrentContext(m_context) != kCGLNoError)
				throw ResourceError("Failed to set current CGL context");
		}
		catch (...)
		{
			CGLReleasePixelFormat(pixelFormat);
			throw;
		}

		CGLReleasePixelFormat(pixelFormat);

		{
			GLFunctionLoader loader(OPENGL_LIBRARY_PATH);
			glu::initFunctions(&m_functions, &loader, config.type.getAPI());
		}

		{
			const glu::ApiType actualApi = getVersion(m_functions);
			if (!contextSupports(glu::ContextType(actualApi, glu::ContextFlags(0)), config.type.getAPI()))
				throw tcu::NotSupportedError("OpenGL version not supported");
		}
	}
	catch (...)
	{
		if (m_context)
		{
			CGLSetCurrentContext(DE_NULL);
			CGLDestroyContext(m_context);
		}
		throw;
	}
}

CGLRenderContext::~CGLRenderContext (void)
{
	CGLSetCurrentContext(DE_NULL);
	if (m_context)
		CGLDestroyContext(m_context);
}

class CGLContextFactory : public glu::ContextFactory
{
public:
	CGLContextFactory (void)
		: glu::ContextFactory("cgl", "CGL Context (surfaceless, use fbo)")
	{
	}

	glu::RenderContext*	createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const
	{
		return new CGLRenderContext(config);
	}
};

OSXPlatform::OSXPlatform (void)
{
	m_contextFactoryRegistry.registerFactory(new CGLContextFactory());
}

OSXPlatform::~OSXPlatform (void)
{
}

} // tcu

tcu::Platform* createPlatform (void)
{
	return new tcu::OSXPlatform();
}
