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

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 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;			}

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

	glu::ContextType				m_contextType;

	Win32Window						m_window;
	wgl::Context*					m_context;

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

WGLContext::WGLContext (HINSTANCE instance, const wgl::Core& wglCore, 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");

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

	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;
}

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

} // anonymous

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

glu::RenderContext* WGLContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const
{
	return new WGLContext(m_instance, m_wglCore, config);
}

} // tcu
