1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief WGL Utilities.
22 *//*--------------------------------------------------------------------*/
23
24#include "tcuWGL.hpp"
25#include "tcuWin32Window.hpp"
26#include "deDynamicLibrary.hpp"
27#include "deMemory.h"
28#include "deStringUtil.hpp"
29#include "tcuFormatUtil.hpp"
30#include "gluRenderConfig.hpp"
31#include "glwEnums.hpp"
32
33#include <map>
34#include <sstream>
35#include <iterator>
36#include <set>
37
38#include <wingdi.h>
39
40// WGL_ARB_pixel_format
41#define WGL_NUMBER_PIXEL_FORMATS_ARB				0x2000
42#define WGL_DRAW_TO_WINDOW_ARB						0x2001
43#define WGL_DRAW_TO_BITMAP_ARB						0x2002
44#define WGL_ACCELERATION_ARB						0x2003
45#define WGL_NEED_PALETTE_ARB						0x2004
46#define WGL_NEED_SYSTEM_PALETTE_ARB					0x2005
47#define WGL_SWAP_LAYER_BUFFERS_ARB					0x2006
48#define WGL_SWAP_METHOD_ARB							0x2007
49#define WGL_NUMBER_OVERLAYS_ARB						0x2008
50#define WGL_NUMBER_UNDERLAYS_ARB					0x2009
51#define WGL_TRANSPARENT_ARB							0x200A
52#define WGL_TRANSPARENT_RED_VALUE_ARB				0x2037
53#define WGL_TRANSPARENT_GREEN_VALUE_ARB				0x2038
54#define WGL_TRANSPARENT_BLUE_VALUE_ARB				0x2039
55#define WGL_TRANSPARENT_ALPHA_VALUE_ARB				0x203A
56#define WGL_TRANSPARENT_INDEX_VALUE_ARB				0x203B
57#define WGL_SHARE_DEPTH_ARB							0x200C
58#define WGL_SHARE_STENCIL_ARB						0x200D
59#define WGL_SHARE_ACCUM_ARB							0x200E
60#define WGL_SUPPORT_GDI_ARB							0x200F
61#define WGL_SUPPORT_OPENGL_ARB						0x2010
62#define WGL_DOUBLE_BUFFER_ARB						0x2011
63#define WGL_STEREO_ARB								0x2012
64#define WGL_PIXEL_TYPE_ARB							0x2013
65#define WGL_COLOR_BITS_ARB							0x2014
66#define WGL_RED_BITS_ARB							0x2015
67#define WGL_RED_SHIFT_ARB							0x2016
68#define WGL_GREEN_BITS_ARB							0x2017
69#define WGL_GREEN_SHIFT_ARB							0x2018
70#define WGL_BLUE_BITS_ARB							0x2019
71#define WGL_BLUE_SHIFT_ARB							0x201A
72#define WGL_ALPHA_BITS_ARB							0x201B
73#define WGL_ALPHA_SHIFT_ARB							0x201C
74#define WGL_ACCUM_BITS_ARB							0x201D
75#define WGL_ACCUM_RED_BITS_ARB						0x201E
76#define WGL_ACCUM_GREEN_BITS_ARB					0x201F
77#define WGL_ACCUM_BLUE_BITS_ARB						0x2020
78#define WGL_ACCUM_ALPHA_BITS_ARB					0x2021
79#define WGL_DEPTH_BITS_ARB							0x2022
80#define WGL_STENCIL_BITS_ARB						0x2023
81#define WGL_AUX_BUFFERS_ARB							0x2024
82
83#define WGL_NO_ACCELERATION_ARB						0x2025
84#define WGL_GENERIC_ACCELERATION_ARB				0x2026
85#define WGL_FULL_ACCELERATION_ARB					0x2027
86
87#define WGL_TYPE_RGBA_ARB							0x202B
88#define WGL_TYPE_COLORINDEX_ARB						0x202C
89
90// WGL_ARB_color_buffer_float
91#define WGL_TYPE_RGBA_FLOAT_ARB						0x21A0
92
93// WGL_EXT_pixel_type_packed_float
94#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT			0x20A8
95
96// WGL_ARB_multisample
97#define WGL_SAMPLE_BUFFERS_ARB						0x2041
98#define WGL_SAMPLES_ARB								0x2042
99
100// WGL_EXT_colorspace
101#define WGL_COLORSPACE_EXT							0x309D
102#define WGL_COLORSPACE_SRGB_EXT						0x3089
103#define WGL_COLORSPACE_LINEAR_EXT					0x308A
104
105// WGL_ARB_create_context
106#define WGL_CONTEXT_MAJOR_VERSION_ARB				0x2091
107#define WGL_CONTEXT_MINOR_VERSION_ARB				0x2092
108#define WGL_CONTEXT_LAYER_PLANE_ARB					0x2093
109#define WGL_CONTEXT_FLAGS_ARB						0x2094
110#define WGL_CONTEXT_PROFILE_MASK_ARB				0x9126
111#define WGL_CONTEXT_DEBUG_BIT_ARB					0x0001
112#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB		0x0002
113#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB			0x00000001
114#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB	0x00000002
115#define WGL_CONTEXT_ES_PROFILE_BIT_EXT				0x00000004
116
117// WGL_ARB_create_context_robustness
118#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB			0x0004
119#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB	0x8256
120#define WGL_NO_RESET_NOTIFICATION_ARB				0x8261
121#define WGL_LOSE_CONTEXT_ON_RESET_ARB				0x8252
122
123// WGL ARB_create_context_no_error
124#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB				0x31B3
125
126DE_BEGIN_EXTERN_C
127
128// WGL core
129typedef HGLRC		(WINAPI* wglCreateContextFunc)				(HDC hdc);
130typedef BOOL		(WINAPI* wglDeleteContextFunc)				(HGLRC hglrc);
131typedef BOOL		(WINAPI* wglMakeCurrentFunc)				(HDC hdc, HGLRC hglrc);
132typedef PROC		(WINAPI* wglGetProcAddressFunc)				(LPCSTR lpszProc);
133typedef BOOL		(WINAPI* wglSwapLayerBuffersFunc)			(HDC dhc, UINT fuPlanes);
134
135// WGL_ARB_pixel_format
136typedef BOOL		(WINAPI* wglGetPixelFormatAttribivARBFunc)	(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
137typedef BOOL		(WINAPI* wglGetPixelFormatAttribfvARBFunc)	(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
138typedef BOOL		(WINAPI* wglChoosePixelFormatARBFunc)		(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
139
140// WGL_ARB_create_context
141typedef HGLRC		(WINAPI* wglCreateContextAttribsARBFunc)	(HDC hdc, HGLRC hshareContext, const int* attribList);
142typedef const char*	(WINAPI* wglGetExtensionsStringARBFunc)		(HDC hdc);
143
144// WGL_EXT_swap_control
145typedef BOOL		(WINAPI* wglSwapIntervalEXTFunc)			(int interval);
146
147DE_END_EXTERN_C
148
149namespace tcu
150{
151namespace wgl
152{
153
154// Functions
155
156struct Functions
157{
158	// Core
159	wglCreateContextFunc				createContext;
160	wglDeleteContextFunc				deleteContext;
161	wglMakeCurrentFunc					makeCurrent;
162	wglGetProcAddressFunc				getProcAddress;
163	wglSwapLayerBuffersFunc				swapLayerBuffers;
164
165	// WGL_ARB_pixel_format
166	wglGetPixelFormatAttribivARBFunc	getPixelFormatAttribivARB;
167	wglGetPixelFormatAttribfvARBFunc	getPixelFormatAttribfvARB;
168	wglChoosePixelFormatARBFunc			choosePixelFormatARB;
169
170	// WGL_ARB_create_context
171	wglCreateContextAttribsARBFunc		createContextAttribsARB;
172	wglGetExtensionsStringARBFunc		getExtensionsStringARB;
173
174	// WGL_EXT_swap_control
175	wglSwapIntervalEXTFunc				swapIntervalEXT;
176
177
178	Functions (void)
179		: createContext				(DE_NULL)
180		, deleteContext				(DE_NULL)
181		, makeCurrent				(DE_NULL)
182		, getProcAddress			(DE_NULL)
183		, swapLayerBuffers			(DE_NULL)
184		, getPixelFormatAttribivARB	(DE_NULL)
185		, getPixelFormatAttribfvARB	(DE_NULL)
186		, choosePixelFormatARB		(DE_NULL)
187		, createContextAttribsARB	(DE_NULL)
188		, getExtensionsStringARB	(DE_NULL)
189	{
190	}
191};
192
193// Library
194
195class Library
196{
197public:
198								Library			(HINSTANCE instance);
199								~Library		(void);
200
201	const Functions&			getFunctions	(void) const	{ return m_functions;	}
202	const de::DynamicLibrary&	getGLLibrary	(void) const	{ return m_library;		}
203	bool						isWglExtensionSupported (const char* extName) const;
204
205private:
206	de::DynamicLibrary			m_library;
207	Functions					m_functions;
208	std::set<std::string>		m_extensions;
209};
210
211Library::Library (HINSTANCE instance)
212	: m_library("opengl32.dll")
213{
214	// Temporary 1x1 window for creating context
215	win32::Window tmpWindow(instance, 1, 1);
216
217	// Load WGL core.
218	m_functions.createContext		= (wglCreateContextFunc)		m_library.getFunction("wglCreateContext");
219	m_functions.deleteContext		= (wglDeleteContextFunc)		m_library.getFunction("wglDeleteContext");
220	m_functions.getProcAddress		= (wglGetProcAddressFunc)		m_library.getFunction("wglGetProcAddress");
221	m_functions.makeCurrent			= (wglMakeCurrentFunc)			m_library.getFunction("wglMakeCurrent");
222	m_functions.swapLayerBuffers	= (wglSwapLayerBuffersFunc)		m_library.getFunction("wglSwapLayerBuffers");
223
224	if (!m_functions.createContext		||
225		!m_functions.deleteContext		||
226		!m_functions.getProcAddress		||
227		!m_functions.makeCurrent		||
228		!m_functions.swapLayerBuffers)
229		throw ResourceError("Failed to load core WGL functions");
230
231	{
232		PIXELFORMATDESCRIPTOR pixelFormatDesc;
233		deMemset(&pixelFormatDesc, 0, sizeof(pixelFormatDesc));
234
235		pixelFormatDesc.nSize			= sizeof(pixelFormatDesc);
236		pixelFormatDesc.nVersion		= 1;
237		pixelFormatDesc.dwFlags			= PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
238		pixelFormatDesc.iPixelType		= PFD_TYPE_RGBA;
239		pixelFormatDesc.iLayerType		= PFD_MAIN_PLANE;
240
241		int pixelFormat = ChoosePixelFormat(tmpWindow.getDeviceContext(), &pixelFormatDesc);
242		if (!SetPixelFormat(tmpWindow.getDeviceContext(), pixelFormat, &pixelFormatDesc))
243			throw ResourceError("Failed to set pixel format for temporary context creation");
244	}
245
246	// Create temporary context for loading extension functions.
247	HGLRC tmpCtx = m_functions.createContext(tmpWindow.getDeviceContext());
248	if (!tmpCtx || !m_functions.makeCurrent(tmpWindow.getDeviceContext(), tmpCtx))
249	{
250		if (tmpCtx)
251			m_functions.deleteContext(tmpCtx);
252		throw ResourceError("Failed to create temporary WGL context");
253	}
254
255	// WGL_ARB_pixel_format
256	m_functions.getPixelFormatAttribivARB	= (wglGetPixelFormatAttribivARBFunc)m_functions.getProcAddress("wglGetPixelFormatAttribivARB");
257	m_functions.getPixelFormatAttribfvARB	= (wglGetPixelFormatAttribfvARBFunc)m_functions.getProcAddress("wglGetPixelFormatAttribfvARB");
258	m_functions.choosePixelFormatARB		= (wglChoosePixelFormatARBFunc)m_functions.getProcAddress("wglChoosePixelFormatARB");
259
260	// WGL_ARB_create_context
261	m_functions.createContextAttribsARB		= (wglCreateContextAttribsARBFunc)m_functions.getProcAddress("wglCreateContextAttribsARB");
262	m_functions.getExtensionsStringARB		= (wglGetExtensionsStringARBFunc)m_functions.getProcAddress("wglGetExtensionsStringARB");
263
264	// WGL_EXT_swap_control
265	m_functions.swapIntervalEXT				= (wglSwapIntervalEXTFunc)m_functions.getProcAddress("wglSwapIntervalEXT");
266
267	m_functions.makeCurrent(tmpWindow.getDeviceContext(), NULL);
268	m_functions.deleteContext(tmpCtx);
269
270	if (!m_functions.getPixelFormatAttribivARB	||
271		!m_functions.getPixelFormatAttribfvARB	||
272		!m_functions.choosePixelFormatARB		||
273		!m_functions.createContextAttribsARB	||
274		!m_functions.getExtensionsStringARB)
275		throw ResourceError("Failed to load WGL extension functions");
276
277	const char* extensions = m_functions.getExtensionsStringARB(tmpWindow.getDeviceContext());
278	std::istringstream extStream(extensions);
279	m_extensions = std::set<std::string>(std::istream_iterator<std::string>(extStream),
280										 std::istream_iterator<std::string>());
281}
282
283Library::~Library (void)
284{
285}
286
287bool Library::isWglExtensionSupported (const char* extName) const
288{
289	return m_extensions.find(extName) != m_extensions.end();
290}
291
292// Core
293
294Core::Core (HINSTANCE instance)
295	: m_library(new Library(instance))
296{
297}
298
299Core::~Core (void)
300{
301	delete m_library;
302}
303
304std::vector<int> Core::getPixelFormats (HDC deviceCtx) const
305{
306	const Functions& wgl = m_library->getFunctions();
307
308	int attribs[] = { WGL_NUMBER_PIXEL_FORMATS_ARB };
309	int values[DE_LENGTH_OF_ARRAY(attribs)];
310
311	if (!wgl.getPixelFormatAttribivARB(deviceCtx, 0, 0, DE_LENGTH_OF_ARRAY(attribs), &attribs[0], &values[0]))
312		TCU_THROW(ResourceError, "Failed to query number of WGL pixel formats");
313
314	std::vector<int> pixelFormats(values[0]);
315	for (int i = 0; i < values[0]; i++)
316		pixelFormats[i] = i+1;
317
318	return pixelFormats;
319}
320
321static PixelFormatInfo::Acceleration translateAcceleration (int accel)
322{
323	switch (accel)
324	{
325		case WGL_NO_ACCELERATION_ARB:		return PixelFormatInfo::ACCELERATION_NONE;
326		case WGL_GENERIC_ACCELERATION_ARB:	return PixelFormatInfo::ACCELERATION_GENERIC;
327		case WGL_FULL_ACCELERATION_ARB:		return PixelFormatInfo::ACCELERATION_FULL;
328		default:							return PixelFormatInfo::ACCELERATION_UNKNOWN;
329	}
330}
331
332static PixelFormatInfo::PixelType translatePixelType (int type)
333{
334	switch (type)
335	{
336		case WGL_TYPE_RGBA_ARB:					return PixelFormatInfo::PIXELTYPE_RGBA;
337		case WGL_TYPE_RGBA_FLOAT_ARB:			return PixelFormatInfo::PIXELTYPE_RGBA_FLOAT;
338		case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:	return PixelFormatInfo::PIXELTYPE_RGBA_UNSIGNED_FLOAT;
339		case WGL_TYPE_COLORINDEX_ARB:			return PixelFormatInfo::PIXELTYPE_COLOR_INDEX;
340		default:								return PixelFormatInfo::PIXELTYPE_UNKNOWN;
341	}
342}
343
344static void getPixelFormatAttribs (const Functions& wgl, HDC deviceCtx, int pixelFormat, int numAttribs, const int* attribs, std::map<int, int>* dst)
345{
346	std::vector<int>	values	(numAttribs);
347
348	if (!wgl.getPixelFormatAttribivARB(deviceCtx, pixelFormat, 0, numAttribs, &attribs[0], &values[0]))
349		TCU_THROW(ResourceError, "Pixel format query failed");
350
351	for (int ndx = 0; ndx < numAttribs; ++ndx)
352		(*dst)[attribs[ndx]] = values[ndx];
353}
354
355PixelFormatInfo Core::getPixelFormatInfo (HDC deviceCtx, int pixelFormat) const
356{
357	std::vector<int>	s_attribsToQuery
358	{
359		WGL_DRAW_TO_WINDOW_ARB,
360		WGL_DRAW_TO_BITMAP_ARB,
361		WGL_ACCELERATION_ARB,
362		WGL_NEED_PALETTE_ARB,
363		WGL_NEED_SYSTEM_PALETTE_ARB,
364		WGL_NUMBER_OVERLAYS_ARB,
365		WGL_NUMBER_UNDERLAYS_ARB,
366		WGL_SUPPORT_OPENGL_ARB,
367		WGL_DOUBLE_BUFFER_ARB,
368		WGL_STEREO_ARB,
369		WGL_PIXEL_TYPE_ARB,
370		WGL_RED_BITS_ARB,
371		WGL_GREEN_BITS_ARB,
372		WGL_BLUE_BITS_ARB,
373		WGL_ALPHA_BITS_ARB,
374		WGL_ACCUM_BITS_ARB,
375		WGL_DEPTH_BITS_ARB,
376		WGL_STENCIL_BITS_ARB,
377		WGL_AUX_BUFFERS_ARB,
378		WGL_SAMPLE_BUFFERS_ARB,
379		WGL_SAMPLES_ARB,
380	};
381	if (getLibrary()->isWglExtensionSupported("WGL_EXT_colorspace"))
382		s_attribsToQuery.push_back(WGL_COLORSPACE_EXT);
383
384	const Functions&	wgl			= m_library->getFunctions();
385	std::map<int, int>	values;
386
387	getPixelFormatAttribs(wgl, deviceCtx, pixelFormat, static_cast<int>(s_attribsToQuery.size()), s_attribsToQuery.data(), &values);
388
389	// Translate values.
390	PixelFormatInfo info;
391
392	info.pixelFormat		= pixelFormat;
393	info.surfaceTypes		|= (values[WGL_DRAW_TO_WINDOW_ARB] ? PixelFormatInfo::SURFACE_WINDOW : 0);
394	info.surfaceTypes		|= (values[WGL_DRAW_TO_BITMAP_ARB] ? PixelFormatInfo::SURFACE_PIXMAP : 0);
395	info.acceleration		= translateAcceleration(values[WGL_ACCELERATION_ARB]);
396	info.needPalette		= values[WGL_NEED_PALETTE_ARB] != 0;
397	info.needSystemPalette	= values[WGL_NEED_SYSTEM_PALETTE_ARB] != 0;
398	info.numOverlays		= values[WGL_NUMBER_OVERLAYS_ARB] != 0;
399	info.numUnderlays		= values[WGL_NUMBER_UNDERLAYS_ARB] != 0;
400	info.supportOpenGL		= values[WGL_SUPPORT_OPENGL_ARB] != 0;
401	info.doubleBuffer		= values[WGL_DOUBLE_BUFFER_ARB] != 0;
402	info.stereo				= values[WGL_STEREO_ARB] != 0;
403	info.pixelType			= translatePixelType(values[WGL_PIXEL_TYPE_ARB]);
404	info.redBits			= values[WGL_RED_BITS_ARB];
405	info.greenBits			= values[WGL_GREEN_BITS_ARB];
406	info.blueBits			= values[WGL_BLUE_BITS_ARB];
407	info.alphaBits			= values[WGL_ALPHA_BITS_ARB];
408	info.accumBits			= values[WGL_ACCUM_BITS_ARB];
409	info.depthBits			= values[WGL_DEPTH_BITS_ARB];
410	info.stencilBits		= values[WGL_STENCIL_BITS_ARB];
411	info.numAuxBuffers		= values[WGL_AUX_BUFFERS_ARB];
412	info.sampleBuffers		= values[WGL_SAMPLE_BUFFERS_ARB];
413	info.samples			= values[WGL_SAMPLES_ARB];
414	info.sRGB				= (getLibrary()->isWglExtensionSupported("WGL_EXT_colorspace")) ? (values[WGL_COLORSPACE_EXT] == WGL_COLORSPACE_SRGB_EXT) : false;
415
416	return info;
417}
418
419// Context
420
421Context::Context (const Core*						core,
422				  HDC								deviceCtx,
423				  const Context*					sharedContext,
424				  glu::ContextType					ctxType,
425				  int								pixelFormat,
426				  glu::ResetNotificationStrategy	resetNotificationStrategy)
427	: m_core		(core)
428	, m_deviceCtx	(deviceCtx)
429	, m_context		(0)
430{
431	const Functions&		wgl				= core->getLibrary()->getFunctions();
432	std::vector<int>		attribList;
433
434	// Context version and profile
435	{
436		int	profileBit	= 0;
437		HGLRC sharedCtx	= DE_NULL;
438		int minor		= ctxType.getMinorVersion();
439		int major		= ctxType.getMajorVersion();
440
441		switch (ctxType.getProfile())
442		{
443			case glu::PROFILE_CORE:
444				profileBit = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
445				if (major == 3 && minor < 3)
446					minor = 3;
447				break;
448
449			case glu::PROFILE_ES:
450				profileBit = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
451				break;
452
453			case glu::PROFILE_COMPATIBILITY:
454				profileBit = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
455				break;
456
457			default:
458				TCU_THROW(NotSupportedError, "Unsupported context type for WGL");
459		}
460
461		attribList.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
462		attribList.push_back(major);
463		attribList.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
464		attribList.push_back(minor);
465		attribList.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
466		attribList.push_back(profileBit);
467	}
468
469	// Context flags
470	{
471		int		flags	= 0;
472
473		if ((ctxType.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0)
474		{
475			if (glu::isContextTypeES(ctxType))
476				TCU_THROW(InternalError, "Only OpenGL core contexts can be forward-compatible");
477
478			flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
479		}
480
481		if ((ctxType.getFlags() & glu::CONTEXT_DEBUG) != 0)
482			flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
483
484		if ((ctxType.getFlags() & glu::CONTEXT_ROBUST) != 0)
485			flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
486
487		if ((ctxType.getFlags() & glu::CONTEXT_NO_ERROR) != 0)
488		{
489			if (core->getLibrary()->isWglExtensionSupported("WGL_ARB_create_context_no_error"))
490			{
491				attribList.push_back(WGL_CONTEXT_OPENGL_NO_ERROR_ARB);
492				attribList.push_back(1);
493			}
494			else
495				TCU_THROW(NotSupportedError, "WGL_ARB_create_context_no_error is required for creating no-error contexts");
496		}
497
498		if (flags != 0)
499		{
500			attribList.push_back(WGL_CONTEXT_FLAGS_ARB);
501			attribList.push_back(flags);
502		}
503	}
504
505	if (resetNotificationStrategy != glu::RESET_NOTIFICATION_STRATEGY_NOT_SPECIFIED)
506	{
507		attribList.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
508
509		if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_NO_RESET_NOTIFICATION)
510			attribList.push_back(WGL_NO_RESET_NOTIFICATION_ARB);
511		else if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_LOSE_CONTEXT_ON_RESET)
512			attribList.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
513		else
514			TCU_THROW(InternalError, "Unknown reset notification strategy");
515	}
516
517	// Set pixel format
518	{
519		PIXELFORMATDESCRIPTOR pixelFormatDesc;
520		deMemset(&pixelFormatDesc, 0, sizeof(pixelFormatDesc));
521
522		if (!DescribePixelFormat(deviceCtx, pixelFormat, sizeof(pixelFormatDesc), &pixelFormatDesc))
523			throw ResourceError("DescribePixelFormat() failed");
524
525		if (!SetPixelFormat(deviceCtx, pixelFormat, &pixelFormatDesc))
526			throw ResourceError("Failed to set pixel format");
527	}
528
529	HGLRC sharedCtx = DE_NULL;
530	if (DE_NULL != sharedContext)
531		sharedCtx = sharedContext->m_context;
532
533	// Terminate attribList
534	attribList.push_back(0);
535
536	// Create context
537	m_context = wgl.createContextAttribsARB(deviceCtx, sharedCtx, &attribList[0]);
538
539	if (!m_context)
540		TCU_THROW(ResourceError, "Failed to create WGL context");
541
542	if (!wgl.makeCurrent(deviceCtx, m_context))
543	{
544		wgl.deleteContext(m_context);
545		TCU_THROW(ResourceError, "wglMakeCurrent() failed");
546	}
547
548	if (core->getLibrary()->isWglExtensionSupported("WGL_EXT_swap_control"))
549		core->getLibrary()->getFunctions().swapIntervalEXT(0);
550}
551
552Context::~Context (void)
553{
554	const Functions& wgl = m_core->getLibrary()->getFunctions();
555
556	wgl.makeCurrent(m_deviceCtx, NULL);
557	wgl.deleteContext(m_context);
558}
559
560FunctionPtr Context::getGLFunction (const char* name) const
561{
562	FunctionPtr ptr = DE_NULL;
563
564	// Try first with wglGeProcAddress()
565	ptr = (FunctionPtr)m_core->getLibrary()->getFunctions().getProcAddress(name);
566
567	// Fall-back to dynlib
568	if (!ptr)
569		ptr = (FunctionPtr)m_core->getLibrary()->getGLLibrary().getFunction(name);
570
571	return ptr;
572}
573
574void Context::makeCurrent (void)
575{
576	const Functions& wgl = m_core->getLibrary()->getFunctions();
577	if (!wgl.makeCurrent(m_deviceCtx, m_context))
578		TCU_THROW(ResourceError, "wglMakeCurrent() failed");
579}
580
581void Context::swapBuffers (void) const
582{
583	const Functions& wgl = m_core->getLibrary()->getFunctions();
584	if (!wgl.swapLayerBuffers(m_deviceCtx, WGL_SWAP_MAIN_PLANE))
585		TCU_THROW(ResourceError, "wglSwapBuffers() failed");
586}
587
588bool isSupportedByTests (const PixelFormatInfo& info)
589{
590	if (!info.supportOpenGL)
591		return false;
592
593	if (info.acceleration != wgl::PixelFormatInfo::ACCELERATION_FULL)
594		return false;
595
596	if (info.pixelType != wgl::PixelFormatInfo::PIXELTYPE_RGBA)
597		return false;
598
599	if ((info.surfaceTypes & wgl::PixelFormatInfo::SURFACE_WINDOW) == 0)
600		return false;
601
602	if (info.needPalette || info.needSystemPalette)
603		return false;
604
605	if (info.numOverlays != 0 || info.numUnderlays != 0)
606		return false;
607
608	if (info.stereo)
609		return false;
610
611	return true;
612}
613
614int choosePixelFormat (const Core& wgl, HDC deviceCtx, const glu::RenderConfig& config)
615{
616	std::vector<int> pixelFormats = wgl.getPixelFormats(deviceCtx);
617
618	for (std::vector<int>::const_iterator fmtIter = pixelFormats.begin(); fmtIter != pixelFormats.end(); ++fmtIter)
619	{
620		const PixelFormatInfo info = wgl.getPixelFormatInfo(deviceCtx, *fmtIter);
621
622		// Skip formats that are fundamentally not compatible with current tests
623		if (!isSupportedByTests(info))
624			continue;
625
626		if (config.redBits != glu::RenderConfig::DONT_CARE &&
627			config.redBits != info.redBits)
628			continue;
629
630		if (config.greenBits != glu::RenderConfig::DONT_CARE &&
631			config.greenBits != info.greenBits)
632			continue;
633
634		if (config.blueBits != glu::RenderConfig::DONT_CARE &&
635			config.blueBits != info.blueBits)
636			continue;
637
638		if (config.alphaBits != glu::RenderConfig::DONT_CARE &&
639			config.alphaBits != info.alphaBits)
640			continue;
641
642		if (config.depthBits != glu::RenderConfig::DONT_CARE &&
643			config.depthBits != info.depthBits)
644			continue;
645
646		if (config.stencilBits != glu::RenderConfig::DONT_CARE &&
647			config.stencilBits != info.stencilBits)
648			continue;
649
650		if (config.numSamples != glu::RenderConfig::DONT_CARE &&
651			config.numSamples != info.samples)
652			continue;
653
654		// Passed all tests - select this.
655		return info.pixelFormat;
656	}
657
658	return -1;
659}
660
661} // wgl
662} // tcu
663