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 Win32 GLES3 wrapper platform.
22 *//*--------------------------------------------------------------------*/
23
24#include "tcuWin32GLES3Platform.hpp"
25#include "gluRenderConfig.hpp"
26#include "gluRenderContext.hpp"
27#include "tcuRenderTarget.hpp"
28#include "gl3Context.h"
29#include "glwInitES30Direct.hpp"
30
31struct gl3PlatformContext_s
32{
33	tcu::wgl::Context*	context;
34
35	gl3PlatformContext_s (void)
36		: context(DE_NULL)
37	{
38	}
39};
40
41gl3FunctionPtr gl3PlatformContext_getProcAddress (gl3PlatformContext* platformCtx, const char* procName)
42{
43	DE_ASSERT(platformCtx && platformCtx->context);
44	return platformCtx->context->getGLFunction(procName);
45}
46
47namespace tcu
48{
49
50enum
51{
52	DEFAULT_WINDOW_WIDTH	= 400,
53	DEFAULT_WINDOW_HEIGHT	= 300
54};
55
56// Win32GLES3Context
57
58class Win32GLES3Context : public glu::RenderContext
59{
60public:
61									Win32GLES3Context			(const wgl::Core& wgl, HINSTANCE instance, const glu::RenderConfig& config);
62									~Win32GLES3Context			(void);
63
64	glu::ContextType				getType						(void) const	{ return glu::CONTEXTTYPE_ES3;	}
65	const RenderTarget&				getRenderTarget				(void) const	{ return m_renderTarget;		}
66	void							postIterate					(void);
67	const glw::Functions&			getFunctions				(void) const	{ return m_functions;			}
68
69private:
70									Win32GLES3Context			(const Win32GLES3Context& other);
71	Win32GLES3Context&				operator=					(const Win32GLES3Context& other);
72
73	RenderTarget					m_renderTarget;
74	Win32Window						m_window;
75
76	gl3PlatformContext				m_platformCtx;
77	gl3Context*						m_context;
78
79	glw::Functions					m_functions;
80};
81
82typedef const char* (GL_APIENTRY* glGetStringHackFunc) (GLenum str);
83
84Win32GLES3Context::Win32GLES3Context (const wgl::Core& wgl, HINSTANCE instance, const glu::RenderConfig& config)
85	: m_renderTarget(config.width	!= glu::RenderConfig::DONT_CARE ? config.width	: DEFAULT_WINDOW_WIDTH,
86					 config.height	!= glu::RenderConfig::DONT_CARE ? config.height	: DEFAULT_WINDOW_HEIGHT,
87					 PixelFormat(8, 8, 8, 8), 24, 8, 0)
88	, m_window		(instance, m_renderTarget.getWidth(), m_renderTarget.getHeight())
89	, m_context		(DE_NULL)
90{
91	const HDC		deviceCtx		= m_window.getDeviceContext();
92	const int		pixelFormat		= wgl::choosePixelFormat(wgl, deviceCtx, config);
93
94	if (pixelFormat < 0)
95		throw NotSupportedError("No compatible WGL pixel format found");
96
97	m_platformCtx.context = new wgl::Context(&wgl, m_window.getDeviceContext(), wgl::PROFILE_COMPATIBILITY, 3, 3, pixelFormat);
98
99	try
100	{
101		m_context = gl3Context_create(&m_platformCtx);
102		if (!m_context)
103			throw ResourceError("Failed to create GLES3 wrapper context");
104
105		gl3Context_setCurrentContext(m_context);
106		glw::initES30Direct(&m_functions);
107
108		m_window.setVisible(config.windowVisibility != glu::RenderConfig::VISIBILITY_HIDDEN);
109
110		{
111			const wgl::PixelFormatInfo	info	= wgl.getPixelFormatInfo(deviceCtx, pixelFormat);
112			const IVec2					size	= m_window.getSize();
113
114			m_renderTarget = tcu::RenderTarget(size.x(), size.y(),
115											   tcu::PixelFormat(info.redBits, info.greenBits, info.blueBits, info.alphaBits),
116											   info.depthBits, info.stencilBits,
117											   info.sampleBuffers ? info.samples : 0);
118		}
119	}
120	catch (...)
121	{
122		if (m_context)
123			gl3Context_destroy(m_context);
124		delete m_platformCtx.context;
125		throw;
126	}
127}
128
129Win32GLES3Context::~Win32GLES3Context (void)
130{
131	if (m_context)
132		gl3Context_destroy(m_context);
133
134	delete m_platformCtx.context;
135}
136
137void Win32GLES3Context::postIterate (void)
138{
139	m_platformCtx.context->swapBuffers();
140}
141
142// Win32GLES3ContextFactory
143
144class Win32GLES3ContextFactory : public glu::ContextFactory
145{
146public:
147								Win32GLES3ContextFactory	(HINSTANCE instance);
148								~Win32GLES3ContextFactory	(void);
149
150	virtual glu::RenderContext*	createContext				(const glu::RenderConfig& config, const tcu::CommandLine& cmdLine) const;
151
152private:
153	const HINSTANCE				m_instance;
154	wgl::Core					m_wglCore;
155};
156
157Win32GLES3ContextFactory::Win32GLES3ContextFactory (HINSTANCE instance)
158	: glu::ContextFactory	("gles3_wrapper",	"GLES3 Wrapper Context")
159	, m_instance			(instance)
160	, m_wglCore				(instance)
161{
162}
163
164Win32GLES3ContextFactory::~Win32GLES3ContextFactory (void)
165{
166}
167
168glu::RenderContext* Win32GLES3ContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine&) const
169{
170	if (config.type == glu::CONTEXTTYPE_ES3)
171		return new Win32GLES3Context(m_wglCore, m_instance, config);
172	else
173		throw NotSupportedError("Unsupported rendering context type");
174}
175
176// Win32GLES3Platform
177
178Win32GLES3Platform::Win32GLES3Platform (void)
179{
180	const HINSTANCE instance = GetModuleHandle(NULL);
181
182	// Set priority to lower.
183	SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
184
185	m_glContextFactoryRegistry.registerFactory(new Win32GLES3ContextFactory(instance));
186}
187
188Win32GLES3Platform::~Win32GLES3Platform (void)
189{
190}
191
192bool Win32GLES3Platform::processEvents (void)
193{
194	MSG msg;
195	while (PeekMessage(&msg, NULL, 0, 0, TRUE))
196	{
197		DispatchMessage(&msg);
198		if (msg.message == WM_QUIT)
199			return false;
200	}
201	return true;
202}
203
204} // tcu
205
206// Platform factory
207tcu::Platform* createPlatform (void)
208{
209	return new tcu::Win32GLES3Platform();
210}
211