/*-------------------------------------------------------------------------
 * 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 Utilities.
 *//*--------------------------------------------------------------------*/

#include "tcuWGL.hpp"
#include "tcuWin32Window.hpp"
#include "deDynamicLibrary.hpp"
#include "deMemory.h"
#include "deStringUtil.hpp"
#include "tcuFormatUtil.hpp"
#include "gluRenderConfig.hpp"
#include "glwEnums.hpp"

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

#include <WinGDI.h>

// WGL_ARB_pixel_format
#define WGL_NUMBER_PIXEL_FORMATS_ARB				0x2000
#define WGL_DRAW_TO_WINDOW_ARB						0x2001
#define WGL_DRAW_TO_BITMAP_ARB						0x2002
#define WGL_ACCELERATION_ARB						0x2003
#define WGL_NEED_PALETTE_ARB						0x2004
#define WGL_NEED_SYSTEM_PALETTE_ARB					0x2005
#define WGL_SWAP_LAYER_BUFFERS_ARB					0x2006
#define WGL_SWAP_METHOD_ARB							0x2007
#define WGL_NUMBER_OVERLAYS_ARB						0x2008
#define WGL_NUMBER_UNDERLAYS_ARB					0x2009
#define WGL_TRANSPARENT_ARB							0x200A
#define WGL_TRANSPARENT_RED_VALUE_ARB				0x2037
#define WGL_TRANSPARENT_GREEN_VALUE_ARB				0x2038
#define WGL_TRANSPARENT_BLUE_VALUE_ARB				0x2039
#define WGL_TRANSPARENT_ALPHA_VALUE_ARB				0x203A
#define WGL_TRANSPARENT_INDEX_VALUE_ARB				0x203B
#define WGL_SHARE_DEPTH_ARB							0x200C
#define WGL_SHARE_STENCIL_ARB						0x200D
#define WGL_SHARE_ACCUM_ARB							0x200E
#define WGL_SUPPORT_GDI_ARB							0x200F
#define WGL_SUPPORT_OPENGL_ARB						0x2010
#define WGL_DOUBLE_BUFFER_ARB						0x2011
#define WGL_STEREO_ARB								0x2012
#define WGL_PIXEL_TYPE_ARB							0x2013
#define WGL_COLOR_BITS_ARB							0x2014
#define WGL_RED_BITS_ARB							0x2015
#define WGL_RED_SHIFT_ARB							0x2016
#define WGL_GREEN_BITS_ARB							0x2017
#define WGL_GREEN_SHIFT_ARB							0x2018
#define WGL_BLUE_BITS_ARB							0x2019
#define WGL_BLUE_SHIFT_ARB							0x201A
#define WGL_ALPHA_BITS_ARB							0x201B
#define WGL_ALPHA_SHIFT_ARB							0x201C
#define WGL_ACCUM_BITS_ARB							0x201D
#define WGL_ACCUM_RED_BITS_ARB						0x201E
#define WGL_ACCUM_GREEN_BITS_ARB					0x201F
#define WGL_ACCUM_BLUE_BITS_ARB						0x2020
#define WGL_ACCUM_ALPHA_BITS_ARB					0x2021
#define WGL_DEPTH_BITS_ARB							0x2022
#define WGL_STENCIL_BITS_ARB						0x2023
#define WGL_AUX_BUFFERS_ARB							0x2024

#define WGL_NO_ACCELERATION_ARB						0x2025
#define WGL_GENERIC_ACCELERATION_ARB				0x2026
#define WGL_FULL_ACCELERATION_ARB					0x2027

#define WGL_TYPE_RGBA_ARB							0x202B
#define WGL_TYPE_COLORINDEX_ARB						0x202C

// WGL_ARB_color_buffer_float
#define WGL_TYPE_RGBA_FLOAT_ARB						0x21A0

// WGL_EXT_pixel_type_packed_float
#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT			0x20A8

// WGL_ARB_multisample
#define WGL_SAMPLE_BUFFERS_ARB						0x2041
#define WGL_SAMPLES_ARB								0x2042

// WGL_ARB_create_context
#define WGL_CONTEXT_MAJOR_VERSION_ARB				0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB				0x2092
#define WGL_CONTEXT_LAYER_PLANE_ARB					0x2093
#define WGL_CONTEXT_FLAGS_ARB						0x2094
#define WGL_CONTEXT_PROFILE_MASK_ARB				0x9126
#define WGL_CONTEXT_DEBUG_BIT_ARB					0x0001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB		0x0002
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB			0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB	0x00000002
#define WGL_CONTEXT_ES_PROFILE_BIT_EXT				0x00000004

// WGL_ARB_create_context_robustness
#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB			0x0004
#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB	0x8256
#define WGL_NO_RESET_NOTIFICATION_ARB				0x8261
#define WGL_LOSE_CONTEXT_ON_RESET_ARB				0x8252

// WGL ARB_create_context_no_error
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB				0x31B3

DE_BEGIN_EXTERN_C

// WGL core
typedef HGLRC		(WINAPI* wglCreateContextFunc)				(HDC hdc);
typedef BOOL		(WINAPI* wglDeleteContextFunc)				(HGLRC hglrc);
typedef BOOL		(WINAPI* wglMakeCurrentFunc)				(HDC hdc, HGLRC hglrc);
typedef PROC		(WINAPI* wglGetProcAddressFunc)				(LPCSTR lpszProc);
typedef BOOL		(WINAPI* wglSwapLayerBuffersFunc)			(HDC dhc, UINT fuPlanes);

// WGL_ARB_pixel_format
typedef BOOL		(WINAPI* wglGetPixelFormatAttribivARBFunc)	(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
typedef BOOL		(WINAPI* wglGetPixelFormatAttribfvARBFunc)	(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
typedef BOOL		(WINAPI* wglChoosePixelFormatARBFunc)		(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);

// WGL_ARB_create_context
typedef HGLRC		(WINAPI* wglCreateContextAttribsARBFunc)	(HDC hdc, HGLRC hshareContext, const int* attribList);
typedef const char*	(WINAPI* wglGetExtensionsStringARBFunc)		(HDC hdc);

// WGL_EXT_swap_control
typedef BOOL		(WINAPI* wglSwapIntervalEXTFunc)			(int interval);

DE_END_EXTERN_C

namespace tcu
{
namespace wgl
{

// Functions

struct Functions
{
	// Core
	wglCreateContextFunc				createContext;
	wglDeleteContextFunc				deleteContext;
	wglMakeCurrentFunc					makeCurrent;
	wglGetProcAddressFunc				getProcAddress;
	wglSwapLayerBuffersFunc				swapLayerBuffers;

	// WGL_ARB_pixel_format
	wglGetPixelFormatAttribivARBFunc	getPixelFormatAttribivARB;
	wglGetPixelFormatAttribfvARBFunc	getPixelFormatAttribfvARB;
	wglChoosePixelFormatARBFunc			choosePixelFormatARB;

	// WGL_ARB_create_context
	wglCreateContextAttribsARBFunc		createContextAttribsARB;
	wglGetExtensionsStringARBFunc		getExtensionsStringARB;

	// WGL_EXT_swap_control
	wglSwapIntervalEXTFunc				swapIntervalEXT;


	Functions (void)
		: createContext				(DE_NULL)
		, deleteContext				(DE_NULL)
		, makeCurrent				(DE_NULL)
		, getProcAddress			(DE_NULL)
		, swapLayerBuffers			(DE_NULL)
		, getPixelFormatAttribivARB	(DE_NULL)
		, getPixelFormatAttribfvARB	(DE_NULL)
		, choosePixelFormatARB		(DE_NULL)
		, createContextAttribsARB	(DE_NULL)
		, getExtensionsStringARB	(DE_NULL)
	{
	}
};

// Library

class Library
{
public:
								Library			(HINSTANCE instance);
								~Library		(void);

	const Functions&			getFunctions	(void) const	{ return m_functions;	}
	const de::DynamicLibrary&	getGLLibrary	(void) const	{ return m_library;		}
	bool						isWglExtensionSupported (const char* extName) const;

private:
	de::DynamicLibrary			m_library;
	Functions					m_functions;
	std::set<std::string>		m_extensions;
};

Library::Library (HINSTANCE instance)
	: m_library("opengl32.dll")
{
	// Temporary 1x1 window for creating context
	win32::Window tmpWindow(instance, 1, 1);

	// Load WGL core.
	m_functions.createContext		= (wglCreateContextFunc)		m_library.getFunction("wglCreateContext");
	m_functions.deleteContext		= (wglDeleteContextFunc)		m_library.getFunction("wglDeleteContext");
	m_functions.getProcAddress		= (wglGetProcAddressFunc)		m_library.getFunction("wglGetProcAddress");
	m_functions.makeCurrent			= (wglMakeCurrentFunc)			m_library.getFunction("wglMakeCurrent");
	m_functions.swapLayerBuffers	= (wglSwapLayerBuffersFunc)		m_library.getFunction("wglSwapLayerBuffers");

	if (!m_functions.createContext		||
		!m_functions.deleteContext		||
		!m_functions.getProcAddress		||
		!m_functions.makeCurrent		||
		!m_functions.swapLayerBuffers)
		throw ResourceError("Failed to load core WGL functions");

	{
		PIXELFORMATDESCRIPTOR pixelFormatDesc;
		deMemset(&pixelFormatDesc, 0, sizeof(pixelFormatDesc));

		pixelFormatDesc.nSize			= sizeof(pixelFormatDesc);
		pixelFormatDesc.nVersion		= 1;
		pixelFormatDesc.dwFlags			= PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
		pixelFormatDesc.iPixelType		= PFD_TYPE_RGBA;
		pixelFormatDesc.iLayerType		= PFD_MAIN_PLANE;

		int pixelFormat = ChoosePixelFormat(tmpWindow.getDeviceContext(), &pixelFormatDesc);
		if (!SetPixelFormat(tmpWindow.getDeviceContext(), pixelFormat, &pixelFormatDesc))
			throw ResourceError("Failed to set pixel format for temporary context creation");
	}

	// Create temporary context for loading extension functions.
	HGLRC tmpCtx = m_functions.createContext(tmpWindow.getDeviceContext());
	if (!tmpCtx || !m_functions.makeCurrent(tmpWindow.getDeviceContext(), tmpCtx))
	{
		if (tmpCtx)
			m_functions.deleteContext(tmpCtx);
		throw ResourceError("Failed to create temporary WGL context");
	}

	// WGL_ARB_pixel_format
	m_functions.getPixelFormatAttribivARB	= (wglGetPixelFormatAttribivARBFunc)m_functions.getProcAddress("wglGetPixelFormatAttribivARB");
	m_functions.getPixelFormatAttribfvARB	= (wglGetPixelFormatAttribfvARBFunc)m_functions.getProcAddress("wglGetPixelFormatAttribfvARB");
	m_functions.choosePixelFormatARB		= (wglChoosePixelFormatARBFunc)m_functions.getProcAddress("wglChoosePixelFormatARB");

	// WGL_ARB_create_context
	m_functions.createContextAttribsARB		= (wglCreateContextAttribsARBFunc)m_functions.getProcAddress("wglCreateContextAttribsARB");
	m_functions.getExtensionsStringARB		= (wglGetExtensionsStringARBFunc)m_functions.getProcAddress("wglGetExtensionsStringARB");

	// WGL_EXT_swap_control
	m_functions.swapIntervalEXT				= (wglSwapIntervalEXTFunc)m_functions.getProcAddress("wglSwapIntervalEXT");

	m_functions.makeCurrent(tmpWindow.getDeviceContext(), NULL);
	m_functions.deleteContext(tmpCtx);

	if (!m_functions.getPixelFormatAttribivARB	||
		!m_functions.getPixelFormatAttribfvARB	||
		!m_functions.choosePixelFormatARB		||
		!m_functions.createContextAttribsARB	||
		!m_functions.getExtensionsStringARB)
		throw ResourceError("Failed to load WGL extension functions");

	const char* extensions = m_functions.getExtensionsStringARB(tmpWindow.getDeviceContext());
	std::istringstream extStream(extensions);
	m_extensions = std::set<std::string>(std::istream_iterator<std::string>(extStream),
										 std::istream_iterator<std::string>());
}

Library::~Library (void)
{
}

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

// Core

Core::Core (HINSTANCE instance)
	: m_library(new Library(instance))
{
}

Core::~Core (void)
{
	delete m_library;
}

std::vector<int> Core::getPixelFormats (HDC deviceCtx) const
{
	const Functions& wgl = m_library->getFunctions();

	int attribs[] = { WGL_NUMBER_PIXEL_FORMATS_ARB };
	int values[DE_LENGTH_OF_ARRAY(attribs)];

	if (!wgl.getPixelFormatAttribivARB(deviceCtx, 0, 0, DE_LENGTH_OF_ARRAY(attribs), &attribs[0], &values[0]))
		TCU_THROW(ResourceError, "Failed to query number of WGL pixel formats");

	std::vector<int> pixelFormats(values[0]);
	for (int i = 0; i < values[0]; i++)
		pixelFormats[i] = i+1;

	return pixelFormats;
}

static PixelFormatInfo::Acceleration translateAcceleration (int accel)
{
	switch (accel)
	{
		case WGL_NO_ACCELERATION_ARB:		return PixelFormatInfo::ACCELERATION_NONE;
		case WGL_GENERIC_ACCELERATION_ARB:	return PixelFormatInfo::ACCELERATION_GENERIC;
		case WGL_FULL_ACCELERATION_ARB:		return PixelFormatInfo::ACCELERATION_FULL;
		default:							return PixelFormatInfo::ACCELERATION_UNKNOWN;
	}
}

static PixelFormatInfo::PixelType translatePixelType (int type)
{
	switch (type)
	{
		case WGL_TYPE_RGBA_ARB:					return PixelFormatInfo::PIXELTYPE_RGBA;
		case WGL_TYPE_RGBA_FLOAT_ARB:			return PixelFormatInfo::PIXELTYPE_RGBA_FLOAT;
		case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:	return PixelFormatInfo::PIXELTYPE_RGBA_UNSIGNED_FLOAT;
		case WGL_TYPE_COLORINDEX_ARB:			return PixelFormatInfo::PIXELTYPE_COLOR_INDEX;
		default:								return PixelFormatInfo::PIXELTYPE_UNKNOWN;
	}
}

static void getPixelFormatAttribs (const Functions& wgl, HDC deviceCtx, int pixelFormat, int numAttribs, const int* attribs, std::map<int, int>* dst)
{
	std::vector<int>	values	(numAttribs);

	if (!wgl.getPixelFormatAttribivARB(deviceCtx, pixelFormat, 0, numAttribs, &attribs[0], &values[0]))
		TCU_THROW(ResourceError, "Pixel format query failed");

	for (int ndx = 0; ndx < numAttribs; ++ndx)
		(*dst)[attribs[ndx]] = values[ndx];
}

PixelFormatInfo Core::getPixelFormatInfo (HDC deviceCtx, int pixelFormat) const
{
	static const int	s_attribsToQuery[] =
	{
		WGL_DRAW_TO_WINDOW_ARB,
		WGL_DRAW_TO_BITMAP_ARB,
		WGL_ACCELERATION_ARB,
		WGL_NEED_PALETTE_ARB,
		WGL_NEED_SYSTEM_PALETTE_ARB,
		WGL_NUMBER_OVERLAYS_ARB,
		WGL_NUMBER_UNDERLAYS_ARB,
		WGL_SUPPORT_OPENGL_ARB,
		WGL_DOUBLE_BUFFER_ARB,
		WGL_STEREO_ARB,
		WGL_PIXEL_TYPE_ARB,
		WGL_RED_BITS_ARB,
		WGL_GREEN_BITS_ARB,
		WGL_BLUE_BITS_ARB,
		WGL_ALPHA_BITS_ARB,
		WGL_ACCUM_BITS_ARB,
		WGL_DEPTH_BITS_ARB,
		WGL_STENCIL_BITS_ARB,
		WGL_AUX_BUFFERS_ARB,
		WGL_SAMPLE_BUFFERS_ARB,
		WGL_SAMPLES_ARB,
	};
	const Functions&	wgl			= m_library->getFunctions();
	std::map<int, int>	values;

	getPixelFormatAttribs(wgl, deviceCtx, pixelFormat, DE_LENGTH_OF_ARRAY(s_attribsToQuery), &s_attribsToQuery[0], &values);

	// Translate values.
	PixelFormatInfo info;

	info.pixelFormat		= pixelFormat;
	info.surfaceTypes		|= (values[WGL_DRAW_TO_WINDOW_ARB] ? PixelFormatInfo::SURFACE_WINDOW : 0);
	info.surfaceTypes		|= (values[WGL_DRAW_TO_BITMAP_ARB] ? PixelFormatInfo::SURFACE_PIXMAP : 0);
	info.acceleration		= translateAcceleration(values[WGL_ACCELERATION_ARB]);
	info.needPalette		= values[WGL_NEED_PALETTE_ARB] != 0;
	info.needSystemPalette	= values[WGL_NEED_SYSTEM_PALETTE_ARB] != 0;
	info.numOverlays		= values[WGL_NUMBER_OVERLAYS_ARB] != 0;
	info.numUnderlays		= values[WGL_NUMBER_UNDERLAYS_ARB] != 0;
	info.supportOpenGL		= values[WGL_SUPPORT_OPENGL_ARB] != 0;
	info.doubleBuffer		= values[WGL_DOUBLE_BUFFER_ARB] != 0;
	info.stereo				= values[WGL_STEREO_ARB] != 0;
	info.pixelType			= translatePixelType(values[WGL_PIXEL_TYPE_ARB]);
	info.redBits			= values[WGL_RED_BITS_ARB];
	info.greenBits			= values[WGL_GREEN_BITS_ARB];
	info.blueBits			= values[WGL_BLUE_BITS_ARB];
	info.alphaBits			= values[WGL_ALPHA_BITS_ARB];
	info.accumBits			= values[WGL_ACCUM_BITS_ARB];
	info.depthBits			= values[WGL_DEPTH_BITS_ARB];
	info.stencilBits		= values[WGL_STENCIL_BITS_ARB];
	info.numAuxBuffers		= values[WGL_AUX_BUFFERS_ARB];
	info.sampleBuffers		= values[WGL_SAMPLE_BUFFERS_ARB];
	info.samples			= values[WGL_SAMPLES_ARB];

	return info;
}

// Context

Context::Context (const Core*						core,
				  HDC								deviceCtx,
				  const Context*					sharedContext,
				  glu::ContextType					ctxType,
				  int								pixelFormat,
				  glu::ResetNotificationStrategy	resetNotificationStrategy)
	: m_core		(core)
	, m_deviceCtx	(deviceCtx)
	, m_context		(0)
{
	const Functions&		wgl				= core->getLibrary()->getFunctions();
	std::vector<int>		attribList;

	// Context version and profile
	{
		int	profileBit	= 0;
		HGLRC sharedCtx	= DE_NULL;
		int minor		= ctxType.getMinorVersion();
		int major		= ctxType.getMajorVersion();

		switch (ctxType.getProfile())
		{
			case glu::PROFILE_CORE:
				profileBit = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
				if (major == 3 && minor < 3)
					minor = 3;
				break;

			case glu::PROFILE_ES:
				profileBit = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
				break;

			case glu::PROFILE_COMPATIBILITY:
				profileBit = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
				break;

			default:
				TCU_THROW(NotSupportedError, "Unsupported context type for WGL");
		}

		attribList.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
		attribList.push_back(major);
		attribList.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
		attribList.push_back(minor);
		attribList.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
		attribList.push_back(profileBit);
	}

	// Context flags
	{
		int		flags	= 0;

		if ((ctxType.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0)
		{
			if (glu::isContextTypeES(ctxType))
				TCU_THROW(InternalError, "Only OpenGL core contexts can be forward-compatible");

			flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
		}

		if ((ctxType.getFlags() & glu::CONTEXT_DEBUG) != 0)
			flags |= WGL_CONTEXT_DEBUG_BIT_ARB;

		if ((ctxType.getFlags() & glu::CONTEXT_ROBUST) != 0)
			flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;

		if ((ctxType.getFlags() & glu::CONTEXT_NO_ERROR) != 0)
		{
			if (core->getLibrary()->isWglExtensionSupported("WGL_ARB_create_context_no_error"))
			{
				attribList.push_back(WGL_CONTEXT_OPENGL_NO_ERROR_ARB);
				attribList.push_back(1);
			}
			else
				TCU_THROW(NotSupportedError, "WGL_ARB_create_context_no_error is required for creating no-error contexts");
		}

		if (flags != 0)
		{
			attribList.push_back(WGL_CONTEXT_FLAGS_ARB);
			attribList.push_back(flags);
		}
	}

	if (resetNotificationStrategy != glu::RESET_NOTIFICATION_STRATEGY_NOT_SPECIFIED)
	{
		attribList.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);

		if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_NO_RESET_NOTIFICATION)
			attribList.push_back(WGL_NO_RESET_NOTIFICATION_ARB);
		else if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_LOSE_CONTEXT_ON_RESET)
			attribList.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
		else
			TCU_THROW(InternalError, "Unknown reset notification strategy");
	}

	// Set pixel format
	{
		PIXELFORMATDESCRIPTOR pixelFormatDesc;
		deMemset(&pixelFormatDesc, 0, sizeof(pixelFormatDesc));

		if (!DescribePixelFormat(deviceCtx, pixelFormat, sizeof(pixelFormatDesc), &pixelFormatDesc))
			throw ResourceError("DescribePixelFormat() failed");

		if (!SetPixelFormat(deviceCtx, pixelFormat, &pixelFormatDesc))
			throw ResourceError("Failed to set pixel format");
	}

	HGLRC sharedCtx = DE_NULL;
	if (DE_NULL != sharedContext)
		sharedCtx = sharedContext->m_context;

	// Terminate attribList
	attribList.push_back(0);

	// Create context
	m_context = wgl.createContextAttribsARB(deviceCtx, sharedCtx, &attribList[0]);

	if (!m_context)
		TCU_THROW(ResourceError, "Failed to create WGL context");

	if (!wgl.makeCurrent(deviceCtx, m_context))
	{
		wgl.deleteContext(m_context);
		TCU_THROW(ResourceError, "wglMakeCurrent() failed");
	}

	if (core->getLibrary()->isWglExtensionSupported("WGL_EXT_swap_control"))
		core->getLibrary()->getFunctions().swapIntervalEXT(0);
}

Context::~Context (void)
{
	const Functions& wgl = m_core->getLibrary()->getFunctions();

	wgl.makeCurrent(m_deviceCtx, NULL);
	wgl.deleteContext(m_context);
}

FunctionPtr Context::getGLFunction (const char* name) const
{
	FunctionPtr ptr = DE_NULL;

	// Try first with wglGeProcAddress()
	ptr = (FunctionPtr)m_core->getLibrary()->getFunctions().getProcAddress(name);

	// Fall-back to dynlib
	if (!ptr)
		ptr = (FunctionPtr)m_core->getLibrary()->getGLLibrary().getFunction(name);

	return ptr;
}

void Context::makeCurrent (void)
{
	const Functions& wgl = m_core->getLibrary()->getFunctions();
	if (!wgl.makeCurrent(m_deviceCtx, m_context))
		TCU_THROW(ResourceError, "wglMakeCurrent() failed");
}

void Context::swapBuffers (void) const
{
	const Functions& wgl = m_core->getLibrary()->getFunctions();
	if (!wgl.swapLayerBuffers(m_deviceCtx, WGL_SWAP_MAIN_PLANE))
		TCU_THROW(ResourceError, "wglSwapBuffers() failed");
}

bool isSupportedByTests (const PixelFormatInfo& info)
{
	if (!info.supportOpenGL)
		return false;

	if (info.acceleration != wgl::PixelFormatInfo::ACCELERATION_FULL)
		return false;

	if (info.pixelType != wgl::PixelFormatInfo::PIXELTYPE_RGBA)
		return false;

	if ((info.surfaceTypes & wgl::PixelFormatInfo::SURFACE_WINDOW) == 0)
		return false;

	if (info.needPalette || info.needSystemPalette)
		return false;

	if (info.numOverlays != 0 || info.numUnderlays != 0)
		return false;

	if (info.stereo)
		return false;

	return true;
}

int choosePixelFormat (const Core& wgl, HDC deviceCtx, const glu::RenderConfig& config)
{
	std::vector<int> pixelFormats = wgl.getPixelFormats(deviceCtx);

	for (std::vector<int>::const_iterator fmtIter = pixelFormats.begin(); fmtIter != pixelFormats.end(); ++fmtIter)
	{
		const PixelFormatInfo info = wgl.getPixelFormatInfo(deviceCtx, *fmtIter);

		// Skip formats that are fundamentally not compatible with current tests
		if (!isSupportedByTests(info))
			continue;

		if (config.redBits != glu::RenderConfig::DONT_CARE &&
			config.redBits != info.redBits)
			continue;

		if (config.greenBits != glu::RenderConfig::DONT_CARE &&
			config.greenBits != info.greenBits)
			continue;

		if (config.blueBits != glu::RenderConfig::DONT_CARE &&
			config.blueBits != info.blueBits)
			continue;

		if (config.alphaBits != glu::RenderConfig::DONT_CARE &&
			config.alphaBits != info.alphaBits)
			continue;

		if (config.depthBits != glu::RenderConfig::DONT_CARE &&
			config.depthBits != info.depthBits)
			continue;

		if (config.stencilBits != glu::RenderConfig::DONT_CARE &&
			config.stencilBits != info.stencilBits)
			continue;

		if (config.numSamples != glu::RenderConfig::DONT_CARE &&
			config.numSamples != info.samples)
			continue;

		// Passed all tests - select this.
		return info.pixelFormat;
	}

	return -1;
}

} // wgl
} // tcu
