• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
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 OpenGL ES rendering context.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "gluRenderContext.hpp"
25 #include "gluDefs.hpp"
26 #include "gluRenderConfig.hpp"
27 #include "gluFboRenderContext.hpp"
28 #include "gluPlatform.hpp"
29 #include "gluStrUtil.hpp"
30 #include "glwInitFunctions.hpp"
31 #include "glwEnums.hpp"
32 #include "tcuPlatform.hpp"
33 #include "tcuCommandLine.hpp"
34 #include "deStringUtil.hpp"
35 #include "deSTLUtil.hpp"
36 
37 namespace glu
38 {
39 
40 // RenderContext
41 
getProcAddress(const char *) const42 glw::GenericFuncType RenderContext::getProcAddress (const char*) const
43 {
44 	return (glw::GenericFuncType)DE_NULL;
45 }
46 
makeCurrent(void)47 void RenderContext::makeCurrent (void)
48 {
49 	TCU_THROW(InternalError, "RenderContext::makeCurrent() is not implemented");
50 }
51 
52 // Utilities
53 
versionGreaterOrEqual(ApiType a,ApiType b)54 inline bool versionGreaterOrEqual (ApiType a, ApiType b)
55 {
56 	return a.getMajorVersion() > b.getMajorVersion() ||
57 		   (a.getMajorVersion() == b.getMajorVersion() && a.getMinorVersion() >= b.getMinorVersion());
58 }
59 
contextSupports(ContextType ctxType,ApiType requiredApiType)60 bool contextSupports (ContextType ctxType, ApiType requiredApiType)
61 {
62 	// \todo [2014-10-06 pyry] Check exact forward-compatible restrictions.
63 	const bool forwardCompatible = (ctxType.getFlags() & CONTEXT_FORWARD_COMPATIBLE) != 0;
64 
65 	if (isContextTypeES(ctxType))
66 	{
67 		DE_ASSERT(!forwardCompatible);
68 		return requiredApiType.getProfile() == PROFILE_ES &&
69 			   versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
70 	}
71 	else if (isContextTypeGLCore(ctxType))
72 	{
73 		if (forwardCompatible)
74 			return ctxType.getAPI() == requiredApiType;
75 		else
76 			return requiredApiType.getProfile() == PROFILE_CORE &&
77 				   versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
78 	}
79 	else if (isContextTypeGLCompatibility(ctxType))
80 	{
81 		DE_ASSERT(!forwardCompatible);
82 		return (requiredApiType.getProfile() == PROFILE_CORE || requiredApiType.getProfile() == PROFILE_COMPATIBILITY) &&
83 			   versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
84 	}
85 	else
86 	{
87 		DE_ASSERT(false);
88 		return false;
89 	}
90 }
91 
parseContextFlags(const std::string & flagsStr)92 static ContextFlags parseContextFlags (const std::string& flagsStr)
93 {
94 	const std::vector<std::string>	flagNames	= de::splitString(flagsStr, ',');
95 	ContextFlags					flags		= ContextFlags(0);
96 	static const struct
97 	{
98 		const char*		name;
99 		ContextFlags	flag;
100 	} s_flagMap[] =
101 	{
102 		{ "debug",		CONTEXT_DEBUG	},
103 		{ "robust",		CONTEXT_ROBUST	}
104 	};
105 
106 	for (std::vector<std::string>::const_iterator flagIter = flagNames.begin(); flagIter != flagNames.end(); ++flagIter)
107 	{
108 		int ndx;
109 		for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
110 		{
111 			if (*flagIter == s_flagMap[ndx].name)
112 			{
113 				flags = flags | s_flagMap[ndx].flag;
114 				break;
115 			}
116 		}
117 
118 		if (ndx == DE_LENGTH_OF_ARRAY(s_flagMap))
119 		{
120 			tcu::print("ERROR: Unrecognized GL context flag '%s'\n", flagIter->c_str());
121 			tcu::print("Supported GL context flags:\n");
122 
123 			for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
124 				tcu::print("  %s\n", s_flagMap[ndx].name);
125 
126 			throw tcu::NotSupportedError((std::string("Unknown GL context flag '") + *flagIter + "'").c_str(), DE_NULL, __FILE__, __LINE__);
127 		}
128 	}
129 
130 	return flags;
131 }
132 
createRenderContext(tcu::Platform & platform,const tcu::CommandLine & cmdLine,const RenderConfig & config,const RenderContext * sharedContext)133 RenderContext* createRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, const RenderConfig& config, const RenderContext* sharedContext)
134 {
135 	const ContextFactoryRegistry&	registry		= platform.getGLPlatform().getContextFactoryRegistry();
136 	const char*						factoryName		= cmdLine.getGLContextType();
137 	const ContextFactory*			factory			= DE_NULL;
138 
139 	if (registry.empty())
140 		throw tcu::NotSupportedError("OpenGL is not supported", DE_NULL, __FILE__, __LINE__);
141 
142 	if (factoryName)
143 	{
144 		factory = registry.getFactoryByName(factoryName);
145 
146 		if (!factory)
147 		{
148 			tcu::print("ERROR: Unknown or unsupported GL context type '%s'\n", factoryName);
149 			tcu::print("Supported GL context types:\n");
150 
151 			for (int factoryNdx = 0; factoryNdx < (int)registry.getFactoryCount(); factoryNdx++)
152 			{
153 				const ContextFactory* curFactory = registry.getFactoryByIndex(factoryNdx);
154 				tcu::print("  %s: %s\n", curFactory->getName(), curFactory->getDescription());
155 			}
156 
157 			throw tcu::NotSupportedError((std::string("Unknown GL context type '") + factoryName + "'").c_str(), DE_NULL, __FILE__, __LINE__);
158 		}
159 	}
160 	else
161 		factory = registry.getDefaultFactory();
162 
163 	if (cmdLine.getSurfaceType() == tcu::SURFACETYPE_FBO)
164 	{
165 		if (sharedContext)
166 			TCU_FAIL("Shared context not implemented for  FBO surface type");
167 		return new FboRenderContext(*factory, config, cmdLine);
168 	}
169 	else
170 		return factory->createContext(config, cmdLine, sharedContext);
171 }
172 
createDefaultRenderContext(tcu::Platform & platform,const tcu::CommandLine & cmdLine,ApiType apiType)173 RenderContext* createDefaultRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, ApiType apiType)
174 {
175 	RenderConfig	config;
176 	ContextFlags	ctxFlags	= ContextFlags(0);
177 
178 	if (cmdLine.getGLContextFlags())
179 		ctxFlags = parseContextFlags(cmdLine.getGLContextFlags());
180 
181 	config.type = glu::ContextType(apiType, ctxFlags);
182 	parseRenderConfig(&config, cmdLine);
183 
184 	return createRenderContext(platform, cmdLine, config);
185 }
186 
getExtensions(const glw::Functions & gl,ApiType apiType)187 static std::vector<std::string> getExtensions (const glw::Functions& gl, ApiType apiType)
188 {
189 	using std::vector;
190 	using std::string;
191 
192 	if (apiType.getProfile() == PROFILE_ES && apiType.getMajorVersion() == 2)
193 	{
194 		TCU_CHECK(gl.getString);
195 
196 		const char*	extStr	= (const char*)gl.getString(GL_EXTENSIONS);
197 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS)");
198 
199 		if (extStr)
200 			return de::splitString(extStr);
201 		else
202 			throw tcu::TestError("glGetString(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
203 	}
204 	else
205 	{
206 		int				numExtensions	= 0;
207 		vector<string>	extensions;
208 
209 		TCU_CHECK(gl.getIntegerv && gl.getStringi);
210 
211 		gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
212 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS)");
213 
214 		if (numExtensions > 0)
215 		{
216 			extensions.resize(numExtensions);
217 
218 			for (int ndx = 0; ndx < numExtensions; ndx++)
219 			{
220 				const char* const ext = (const char*)gl.getStringi(GL_EXTENSIONS, ndx);
221 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS)");
222 
223 				if (ext)
224 					extensions[ndx] = ext;
225 				else
226 					throw tcu::TestError("glGetStringi(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
227 			}
228 
229 		}
230 
231 		return extensions;
232 	}
233 }
234 
hasExtension(const glw::Functions & gl,ApiType apiType,const std::string & extension)235 bool hasExtension (const glw::Functions& gl, ApiType apiType, const std::string& extension)
236 {
237 	std::vector<std::string> extensions(getExtensions(gl, apiType));
238 
239 	return de::contains(extensions.begin(), extensions.end(), extension);
240 }
241 
initCoreFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)242 void initCoreFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
243 {
244 	static const struct
245 	{
246 		ApiType		apiType;
247 		void		(*initFunc)		(glw::Functions* gl, const glw::FunctionLoader* loader);
248 	} s_initFuncs[] =
249 	{
250 		{ ApiType::es(2,0),		glw::initES20		},
251 		{ ApiType::es(3,0),		glw::initES30		},
252 		{ ApiType::es(3,1),		glw::initES31		},
253 		{ ApiType::es(3,2),		glw::initES32		},
254 		{ ApiType::core(3,0),	glw::initGL30Core	},
255 		{ ApiType::core(3,1),	glw::initGL31Core	},
256 		{ ApiType::core(3,2),	glw::initGL32Core	},
257 		{ ApiType::core(3,3),	glw::initGL33Core	},
258 		{ ApiType::core(4,0),	glw::initGL40Core	},
259 		{ ApiType::core(4,1),	glw::initGL41Core	},
260 		{ ApiType::core(4,2),	glw::initGL42Core	},
261 		{ ApiType::core(4,3),	glw::initGL43Core	},
262 		{ ApiType::core(4,4),	glw::initGL44Core	},
263 		{ ApiType::core(4,5),	glw::initGL45Core	},
264 		{ ApiType::core(4,6),	glw::initGL46Core	},
265 		// TODO: initialise actual compat functions rather than using core as a dummy
266 		{ ApiType::compatibility(3,2),	glw::initGL32Core	},
267 		{ ApiType::compatibility(3,3),	glw::initGL33Core	},
268 		{ ApiType::compatibility(4,0),	glw::initGL40Core	},
269 		{ ApiType::compatibility(4,1),	glw::initGL41Core	},
270 		{ ApiType::compatibility(4,2),	glw::initGL42Core	},
271 		{ ApiType::compatibility(4,3),	glw::initGL43Core	},
272 		{ ApiType::compatibility(4,4),	glw::initGL44Core	},
273 		{ ApiType::compatibility(4,5),	glw::initGL45Core	},
274 		{ ApiType::compatibility(4,6),	glw::initGL46Core	},
275 	};
276 
277 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_initFuncs); ndx++)
278 	{
279 		if (s_initFuncs[ndx].apiType == apiType)
280 		{
281 			s_initFuncs[ndx].initFunc(dst, loader);
282 			return;
283 		}
284 	}
285 
286 	throw tcu::InternalError(std::string("Don't know how to load functions for ") + de::toString(apiType));
287 }
288 
initExtensionFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)289 void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
290 {
291 	std::vector<std::string> extensions = getExtensions(*dst, apiType);
292 
293 	if (!extensions.empty())
294 	{
295 		std::vector<const char*> extStr(extensions.size());
296 
297 		for (size_t ndx = 0; ndx < extensions.size(); ndx++)
298 			extStr[ndx] = extensions[ndx].c_str();
299 
300 		initExtensionFunctions(dst, loader, apiType, (int)extStr.size(), &extStr[0]);
301 	}
302 }
303 
initExtensionFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType,int numExtensions,const char * const * extensions)304 void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType, int numExtensions, const char* const* extensions)
305 {
306 	if (apiType.getProfile() == PROFILE_ES)
307 		glw::initExtensionsES(dst, loader, numExtensions, extensions);
308 	else
309 		glw::initExtensionsGL(dst, loader, numExtensions, extensions);
310 }
311 
initFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)312 void initFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
313 {
314 	initCoreFunctions(dst, loader, apiType);
315 	initExtensionFunctions(dst, loader, apiType);
316 }
317 
getApiTypeDescription(ApiType type)318 const char* getApiTypeDescription (ApiType type)
319 {
320 	if (type == glu::ApiType::es(2, 0))			return "OpenGL ES 2";
321 	else if (type == glu::ApiType::es(3, 0))	return "OpenGL ES 3";
322 	else if (type == glu::ApiType::es(3, 1))	return "OpenGL ES 3.1";
323 	else if (type == glu::ApiType::es(3, 2))	return "OpenGL ES 3.2";
324 	else if (type == glu::ApiType::core(3, 0))	return "OpenGL 3.0 core";
325 	else if (type == glu::ApiType::core(3, 1))	return "OpenGL 3.1 core";
326 	else if (type == glu::ApiType::core(3, 2))	return "OpenGL 3.2 core";
327 	else if (type == glu::ApiType::core(3, 3))	return "OpenGL 3.3 core";
328 	else if (type == glu::ApiType::core(4, 0))	return "OpenGL 4.0 core";
329 	else if (type == glu::ApiType::core(4, 1))	return "OpenGL 4.1 core";
330 	else if (type == glu::ApiType::core(4, 2))	return "OpenGL 4.2 core";
331 	else if (type == glu::ApiType::core(4, 3))	return "OpenGL 4.3 core";
332 	else if (type == glu::ApiType::core(4, 4))	return "OpenGL 4.4 core";
333 	else if (type == glu::ApiType::core(4, 5))	return "OpenGL 4.5 core";
334 	else if (type == glu::ApiType::core(4, 6))	return "OpenGL 4.6 core";
335 	else if (type == glu::ApiType::compatibility(3, 2))	return "OpenGL 3.2 compatibility";
336 	else if (type == glu::ApiType::compatibility(3, 3))	return "OpenGL 3.3 compatibility";
337 	else if (type == glu::ApiType::compatibility(4, 0))	return "OpenGL 4.0 compatibility";
338 	else if (type == glu::ApiType::compatibility(4, 1))	return "OpenGL 4.1 compatibility";
339 	else if (type == glu::ApiType::compatibility(4, 2))	return "OpenGL 4.2 compatibility";
340 	else if (type == glu::ApiType::compatibility(4, 3))	return "OpenGL 4.3 compatibility";
341 	else if (type == glu::ApiType::compatibility(4, 4))	return "OpenGL 4.4 compatibility";
342 	else if (type == glu::ApiType::compatibility(4, 5))	return "OpenGL 4.5 compatibility";
343 	else if (type == glu::ApiType::compatibility(4, 6))	return "OpenGL 4.6 compatibility";
344 	else										return DE_NULL;
345 }
346 
347 } // glu
348