/*-------------------------------------------------------------------------
 * 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 WGL GL context factory.
 *//*--------------------------------------------------------------------*/

#include "tcuWGLContextFactory.hpp"

#include "gluRenderConfig.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuWin32Window.hpp"
#include "glwFunctions.hpp"
#include "glwInitFunctions.hpp"
#include "deString.h"

using std::vector;

namespace tcu
{
namespace wgl
{
namespace
{

enum
{
	DEFAULT_WINDOW_WIDTH	= 400,
	DEFAULT_WINDOW_HEIGHT	= 300
};

class WGLFunctionLoader : public glw::FunctionLoader
{
public:
	WGLFunctionLoader (const wgl::Context& context)
		: m_context(context)
	{
	}

	glw::GenericFuncType get (const char* name) const
	{
		return (glw::GenericFuncType)m_context.getGLFunction(name);
	}

private:
	const wgl::Context& m_context;
};

class WGLContext : public glu::RenderContext
{
public:
									WGLContext			(HINSTANCE instance, const wgl::Core& wglCore, const WGLContext* sharedContext, const glu::RenderConfig& config);
									~WGLContext			(void);

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

	glw::GenericFuncType			getProcAddress		(const char* name) const;

	void							makeCurrent			(void);

private:
									WGLContext			(const WGLContext& other);
	WGLContext&						operator=			(const WGLContext& other);

	glu::ContextType				m_contextType;

	win32::Window					m_window;
	wgl::Context*					m_context;

	tcu::RenderTarget				m_renderTarget;
	glw::Functions					m_functions;
};

WGLContext::WGLContext (HINSTANCE instance, const wgl::Core& wglCore, const WGLContext* sharedContext, const glu::RenderConfig& config)
	: m_contextType	(config.type)
	, m_window		(instance,
					 config.width	!= glu::RenderConfig::DONT_CARE	? config.width	: DEFAULT_WINDOW_WIDTH,
					 config.height	!= glu::RenderConfig::DONT_CARE	? config.height	: DEFAULT_WINDOW_HEIGHT)
	, m_context		(DE_NULL)
{
	if (config.surfaceType != glu::RenderConfig::SURFACETYPE_WINDOW &&
		config.surfaceType != glu::RenderConfig::SURFACETYPE_DONT_CARE)
		throw NotSupportedError("Unsupported surface type");

	HDC		deviceCtx	= m_window.getDeviceContext();
	int		pixelFormat	= 0;

	if (config.id != glu::RenderConfig::DONT_CARE)
		pixelFormat = config.id;
	else
		pixelFormat = wgl::choosePixelFormat(wglCore, deviceCtx, config);

	if (pixelFormat < 0)
		throw NotSupportedError("Compatible WGL pixel format not found");

	const wgl::Context* sharedCtx = DE_NULL;
	if (DE_NULL != sharedContext)
		sharedCtx = sharedContext->m_context;

	m_context = new wgl::Context(&wglCore, deviceCtx, sharedCtx, config.type, pixelFormat, config.resetNotificationStrategy);

	try
	{
		// Describe selected config & get render target props.
		const wgl::PixelFormatInfo	info	= wglCore.getPixelFormatInfo(deviceCtx, pixelFormat);
		const IVec2					size	= m_window.getSize();

		m_renderTarget = tcu::RenderTarget(size.x(), size.y(),
										   tcu::PixelFormat(info.redBits, info.greenBits, info.blueBits, info.alphaBits),
										   info.depthBits, info.stencilBits,
										   info.sampleBuffers ? info.samples : 0);

		// Load functions
		{
			WGLFunctionLoader funcLoader(*m_context);
			glu::initFunctions(&m_functions, &funcLoader, config.type.getAPI());
		}

		if (config.windowVisibility != glu::RenderConfig::VISIBILITY_VISIBLE &&
			config.windowVisibility != glu::RenderConfig::VISIBILITY_HIDDEN)
			throw NotSupportedError("Unsupported window visibility mode");

		m_window.setVisible(config.windowVisibility != glu::RenderConfig::VISIBILITY_HIDDEN);
	}
	catch (...)
	{
		delete m_context;
		throw;
	}
}

WGLContext::~WGLContext (void)
{
	delete m_context;
}

glw::GenericFuncType WGLContext::getProcAddress (const char* name) const
{
	return m_context->getGLFunction(name);
}

void WGLContext::makeCurrent (void)
{
	m_context->makeCurrent();
}

void WGLContext::postIterate (void)
{
	m_context->swapBuffers();
	m_window.processEvents();
}

} // anonymous

ContextFactory::ContextFactory (HINSTANCE instance)
	: glu::ContextFactory	("wgl", "Windows WGL OpenGL context")
	, m_instance			(instance)
	, m_wglCore				(instance)
{
}

glu::RenderContext* ContextFactory::createContext (const glu::RenderConfig&  config, const tcu::CommandLine&,
												   const glu::RenderContext* sharedContext) const
{
	const WGLContext* sharedWGLContext = static_cast<const WGLContext*>(sharedContext);
	return new WGLContext(m_instance, m_wglCore, sharedWGLContext, config);
}

} // wgl
} // tcu
