/*-------------------------------------------------------------------------
 * 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);

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;

	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");

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

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
