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 GL context factory.
22 *//*--------------------------------------------------------------------*/
23
24#include "tcuWGLContextFactory.hpp"
25
26#include "gluRenderConfig.hpp"
27#include "tcuRenderTarget.hpp"
28#include "tcuWin32Window.hpp"
29#include "glwFunctions.hpp"
30#include "glwInitFunctions.hpp"
31#include "deString.h"
32
33using std::vector;
34
35namespace tcu
36{
37namespace wgl
38{
39namespace
40{
41
42enum
43{
44	DEFAULT_WINDOW_WIDTH	= 400,
45	DEFAULT_WINDOW_HEIGHT	= 300
46};
47
48class WGLFunctionLoader : public glw::FunctionLoader
49{
50public:
51	WGLFunctionLoader (const wgl::Context& context)
52		: m_context(context)
53	{
54	}
55
56	glw::GenericFuncType get (const char* name) const
57	{
58		return (glw::GenericFuncType)m_context.getGLFunction(name);
59	}
60
61private:
62	const wgl::Context& m_context;
63};
64
65class WGLContext : public glu::RenderContext
66{
67public:
68									WGLContext			(HINSTANCE instance, const wgl::Core& wglCore, const WGLContext* sharedContext, const glu::RenderConfig& config);
69									~WGLContext			(void);
70
71	glu::ContextType				getType				(void) const	{ return m_contextType;			}
72	const RenderTarget&				getRenderTarget		(void) const	{ return m_renderTarget;		}
73	void							postIterate			(void);
74	const glw::Functions&			getFunctions		(void) const	{ return m_functions;			}
75
76	glw::GenericFuncType			getProcAddress		(const char* name) const;
77
78	void							makeCurrent			(void);
79
80private:
81									WGLContext			(const WGLContext& other);
82	WGLContext&						operator=			(const WGLContext& other);
83
84	glu::ContextType				m_contextType;
85
86	win32::Window					m_window;
87	wgl::Context*					m_context;
88
89	tcu::RenderTarget				m_renderTarget;
90	glw::Functions					m_functions;
91};
92
93WGLContext::WGLContext (HINSTANCE instance, const wgl::Core& wglCore, const WGLContext* sharedContext, const glu::RenderConfig& config)
94	: m_contextType	(config.type)
95	, m_window		(instance,
96					 config.width	!= glu::RenderConfig::DONT_CARE	? config.width	: DEFAULT_WINDOW_WIDTH,
97					 config.height	!= glu::RenderConfig::DONT_CARE	? config.height	: DEFAULT_WINDOW_HEIGHT)
98	, m_context		(DE_NULL)
99{
100	if (config.surfaceType != glu::RenderConfig::SURFACETYPE_WINDOW &&
101		config.surfaceType != glu::RenderConfig::SURFACETYPE_DONT_CARE)
102		throw NotSupportedError("Unsupported surface type");
103
104	HDC		deviceCtx	= m_window.getDeviceContext();
105	int		pixelFormat	= 0;
106
107	if (config.id != glu::RenderConfig::DONT_CARE)
108		pixelFormat = config.id;
109	else
110		pixelFormat = wgl::choosePixelFormat(wglCore, deviceCtx, config);
111
112	if (pixelFormat < 0)
113		throw NotSupportedError("Compatible WGL pixel format not found");
114
115	const wgl::Context* sharedCtx = DE_NULL;
116	if (DE_NULL != sharedContext)
117		sharedCtx = sharedContext->m_context;
118
119	m_context = new wgl::Context(&wglCore, deviceCtx, sharedCtx, config.type, pixelFormat, config.resetNotificationStrategy);
120
121	try
122	{
123		// Describe selected config & get render target props.
124		const wgl::PixelFormatInfo	info	= wglCore.getPixelFormatInfo(deviceCtx, pixelFormat);
125		const IVec2					size	= m_window.getSize();
126
127		m_renderTarget = tcu::RenderTarget(size.x(), size.y(),
128										   tcu::PixelFormat(info.redBits, info.greenBits, info.blueBits, info.alphaBits),
129										   info.depthBits, info.stencilBits,
130										   info.sampleBuffers ? info.samples : 0);
131
132		// Load functions
133		{
134			WGLFunctionLoader funcLoader(*m_context);
135			glu::initFunctions(&m_functions, &funcLoader, config.type.getAPI());
136		}
137
138		if (config.windowVisibility != glu::RenderConfig::VISIBILITY_VISIBLE &&
139			config.windowVisibility != glu::RenderConfig::VISIBILITY_HIDDEN)
140			throw NotSupportedError("Unsupported window visibility mode");
141
142		m_window.setVisible(config.windowVisibility != glu::RenderConfig::VISIBILITY_HIDDEN);
143	}
144	catch (...)
145	{
146		delete m_context;
147		throw;
148	}
149}
150
151WGLContext::~WGLContext (void)
152{
153	delete m_context;
154}
155
156glw::GenericFuncType WGLContext::getProcAddress (const char* name) const
157{
158	return m_context->getGLFunction(name);
159}
160
161void WGLContext::makeCurrent (void)
162{
163	m_context->makeCurrent();
164}
165
166void WGLContext::postIterate (void)
167{
168	m_context->swapBuffers();
169	m_window.processEvents();
170}
171
172} // anonymous
173
174ContextFactory::ContextFactory (HINSTANCE instance)
175	: glu::ContextFactory	("wgl", "Windows WGL OpenGL context")
176	, m_instance			(instance)
177	, m_wglCore				(instance)
178{
179}
180
181glu::RenderContext* ContextFactory::createContext (const glu::RenderConfig&  config, const tcu::CommandLine&,
182												   const glu::RenderContext* sharedContext) const
183{
184	const WGLContext* sharedWGLContext = static_cast<const WGLContext*>(sharedContext);
185	return new WGLContext(m_instance, m_wglCore, sharedWGLContext, config);
186}
187
188} // wgl
189} // tcu
190