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