1#ifndef _GLURENDERCONTEXT_HPP
2#define _GLURENDERCONTEXT_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program OpenGL ES Utilities
5 * ------------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief OpenGL ES rendering context.
24 *//*--------------------------------------------------------------------*/
25
26#include "tcuDefs.hpp"
27
28// glw::GenericFuncType
29#include "glwFunctionLoader.hpp"
30
31namespace tcu
32{
33class CommandLine;
34class Platform;
35class RenderTarget;
36}
37
38namespace glw
39{
40class Functions;
41class FunctionLoader;
42}
43
44namespace glu
45{
46
47class ContextType;
48class ContextInfo;
49struct RenderConfig;
50
51enum Profile
52{
53	PROFILE_ES = 0,			//!< OpenGL ES
54	PROFILE_CORE,			//!< OpenGL Core Profile
55	PROFILE_COMPATIBILITY,	//!< OpenGL Compatibility Profile
56
57	PROFILE_LAST
58};
59
60enum ContextFlags
61{
62	CONTEXT_ROBUST				= (1<<0),	//!< Robust context
63	CONTEXT_DEBUG				= (1<<1),	//!< Debug context
64	CONTEXT_FORWARD_COMPATIBLE	= (1<<2),	//!< Forward-compatible context
65	CONTEXT_NO_ERROR			= (1<<3)    //!< No error context
66};
67
68inline ContextFlags	operator| (ContextFlags a, ContextFlags b)	{ return ContextFlags((deUint32)a|(deUint32)b);	}
69inline ContextFlags	operator& (ContextFlags a, ContextFlags b)	{ return ContextFlags((deUint32)a&(deUint32)b);	}
70inline ContextFlags	operator~ (ContextFlags a)					{ return ContextFlags(~(deUint32)a);			}
71
72/*--------------------------------------------------------------------*//*!
73 * \brief Rendering API version and profile.
74 *//*--------------------------------------------------------------------*/
75class ApiType
76{
77public:
78						ApiType			(void) : m_bits(pack(0, 0, PROFILE_LAST)) {}
79						ApiType			(int major, int minor, Profile profile) : m_bits(pack(major, minor, profile)) {}
80
81	int					getMajorVersion	(void) const	{ return int((m_bits>>MAJOR_SHIFT)			& ((1u<<MAJOR_BITS)-1u));	}
82	int					getMinorVersion	(void) const	{ return int((m_bits>>MINOR_SHIFT)			& ((1u<<MINOR_BITS)-1u));	}
83	Profile				getProfile		(void) const	{ return Profile((m_bits>>PROFILE_SHIFT)	& ((1u<<PROFILE_BITS)-1u));	}
84
85	bool				operator==		(ApiType other) const	{ return m_bits == other.m_bits;						}
86	bool				operator!=		(ApiType other) const	{ return m_bits != other.m_bits;						}
87
88	deUint32			getPacked		(void) const	{ return m_bits;												}
89
90	// Shorthands
91	static ApiType		es				(int major, int minor)	{ return ApiType(major, minor, PROFILE_ES);				}
92	static ApiType		core			(int major, int minor)	{ return ApiType(major, minor, PROFILE_CORE);			}
93	static ApiType		compatibility	(int major, int minor)	{ return ApiType(major, minor, PROFILE_COMPATIBILITY);	}
94
95protected:
96						ApiType			(deUint32 bits) : m_bits(bits) {}
97	static ApiType		fromBits		(deUint32 bits)	{ return ApiType(bits);	}
98
99	static deUint32		pack			(int major, int minor, Profile profile);
100
101	deUint32			m_bits;
102
103	enum
104	{
105		MAJOR_BITS		= 4,
106		MINOR_BITS		= 4,
107		PROFILE_BITS	= 2,
108		TOTAL_API_BITS	= MAJOR_BITS+MINOR_BITS+PROFILE_BITS,
109
110		MAJOR_SHIFT		= 0,
111		MINOR_SHIFT		= MAJOR_SHIFT+MAJOR_BITS,
112		PROFILE_SHIFT	= MINOR_SHIFT+MINOR_BITS
113	};
114} DE_WARN_UNUSED_TYPE;
115
116inline deUint32 ApiType::pack (int major, int minor, Profile profile)
117{
118	deUint32 bits = 0;
119
120	DE_ASSERT((deUint32(major) & ~((1<<MAJOR_BITS)-1)) == 0);
121	DE_ASSERT((deUint32(minor) & ~((1<<MINOR_BITS)-1)) == 0);
122	DE_ASSERT((deUint32(profile) & ~((1<<PROFILE_BITS)-1)) == 0);
123
124	bits |= deUint32(major) << MAJOR_SHIFT;
125	bits |= deUint32(minor) << MINOR_SHIFT;
126	bits |= deUint32(profile) << PROFILE_SHIFT;
127
128	return bits;
129}
130
131/*--------------------------------------------------------------------*//*!
132 * \brief Rendering context type.
133 *
134 * ContextType differs from API type by adding context flags. They are
135 * crucial in for example determining when GL core context supports
136 * certain API version (forward-compatible bit).
137 *
138 * \note You should NEVER compare ContextTypes against each other, as
139 *       you most likely don't want to take flags into account. For example
140 *       the test code almost certainly doesn't want to check that you have
141 *       EXACTLY ES3.1 context with debug, but without for example robustness.
142 *//*--------------------------------------------------------------------*/
143class ContextType : private ApiType
144{
145public:
146						ContextType		(void) {}
147						ContextType		(int major, int minor, Profile profile, ContextFlags flags = ContextFlags(0));
148	explicit			ContextType		(ApiType apiType, ContextFlags flags = ContextFlags(0));
149
150	ApiType				getAPI			(void) const	{ return ApiType::fromBits(m_bits & ((1u<<TOTAL_API_BITS)-1u));			}
151	void				setAPI			(const ApiType& apiType)	{ m_bits = apiType.getPacked();								}
152
153	ContextFlags		getFlags		(void) const	{ return ContextFlags((m_bits>>FLAGS_SHIFT)	& ((1u<<FLAGS_BITS)-1u));	}
154
155	using ApiType::getMajorVersion;
156	using ApiType::getMinorVersion;
157	using ApiType::getProfile;
158
159protected:
160	static deUint32		pack			(deUint32 apiBits, ContextFlags flags);
161
162	enum
163	{
164		FLAGS_BITS			= 4,
165		TOTAL_CONTEXT_BITS	= TOTAL_API_BITS+FLAGS_BITS,
166		FLAGS_SHIFT			= TOTAL_API_BITS
167	};
168} DE_WARN_UNUSED_TYPE;
169
170inline ContextType::ContextType (int major, int minor, Profile profile, ContextFlags flags)
171	: ApiType(major, minor, profile)
172{
173	m_bits = pack(m_bits, flags);
174}
175
176inline ContextType::ContextType (ApiType apiType, ContextFlags flags)
177	: ApiType(apiType)
178{
179	m_bits = pack(m_bits, flags);
180}
181
182inline deUint32 ContextType::pack (deUint32 apiBits, ContextFlags flags)
183{
184	deUint32 bits = apiBits;
185
186	DE_ASSERT((deUint32(flags) & ~((1u<<FLAGS_BITS)-1u)) == 0);
187
188	bits |= deUint32(flags) << FLAGS_SHIFT;
189
190	return bits;
191}
192
193inline bool		isContextTypeES				(ContextType type)	{ return type.getAPI().getProfile() == PROFILE_ES;				}
194inline bool		isContextTypeGLCore			(ContextType type)	{ return type.getAPI().getProfile() == PROFILE_CORE;			}
195inline bool		isContextTypeGLCompatibility(ContextType type)	{ return type.getAPI().getProfile() == PROFILE_COMPATIBILITY;	}
196inline bool		isES2Context				(ContextType type)	{ return isContextTypeES(type) && type.getMajorVersion() == 2; }
197bool			contextSupports				(ContextType ctxType, ApiType requiredApiType);
198
199const char*		getApiTypeDescription		(ApiType type);
200
201/*--------------------------------------------------------------------*//*!
202 * \brief Rendering context abstraction.
203 *//*--------------------------------------------------------------------*/
204class RenderContext
205{
206public:
207										RenderContext			(void) {}
208	virtual								~RenderContext			(void) {}
209
210	//! Get context type. Must match to type given to ContextFactory::createContext().
211	virtual ContextType					getType					(void) const	= DE_NULL;
212
213	//! Get GL function table. Should be filled with all core entry points for context type.
214	virtual const glw::Functions&		getFunctions			(void) const	= DE_NULL;
215
216	//! Get render target information.
217	virtual const tcu::RenderTarget&	getRenderTarget			(void) const	= DE_NULL;
218
219	//! Do post-render actions (swap buffers for example).
220	virtual void						postIterate				(void)			= DE_NULL;
221
222	//! Get default framebuffer.
223	virtual deUint32					getDefaultFramebuffer	(void) const { return 0; }
224
225	//! Get extension function address.
226	virtual glw::GenericFuncType		getProcAddress			(const char* name) const;
227
228	//! Make context current in thread. Optional to support.
229	virtual void						makeCurrent				(void);
230
231private:
232										RenderContext			(const RenderContext& other); // Not allowed!
233	RenderContext&						operator=				(const RenderContext& other); // Not allowed!
234};
235
236// Utilities
237
238RenderContext*		createRenderContext				(tcu::Platform& platform, const tcu::CommandLine& cmdLine, const RenderConfig& config, const RenderContext* sharedContext = DE_NULL);
239RenderContext*		createDefaultRenderContext		(tcu::Platform& platform, const tcu::CommandLine& cmdLine, ApiType apiType);
240
241void				initCoreFunctions				(glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType);
242void				initExtensionFunctions			(glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType, int numExtensions, const char* const* extensions);
243
244// \note initFunctions() and initExtensionFunctions() without explicit extension list
245//		 use glGetString* to query list of extensions, so it needs current GL context.
246void				initFunctions					(glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType);
247void				initExtensionFunctions			(glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType);
248
249bool				hasExtension					(const glw::Functions& gl, ApiType apiType, const std::string& extension);
250
251} // glu
252
253#endif // _GLURENDERCONTEXT_HPP
254