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 && versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
69 }
70 else if (isContextTypeGLCore(ctxType))
71 {
72 if (forwardCompatible)
73 return ctxType.getAPI() == requiredApiType;
74 else
75 return requiredApiType.getProfile() == PROFILE_CORE &&
76 versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
77 }
78 else if (isContextTypeGLCompatibility(ctxType))
79 {
80 DE_ASSERT(!forwardCompatible);
81 return (requiredApiType.getProfile() == PROFILE_CORE ||
82 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[] = {{"debug", CONTEXT_DEBUG}, {"robust", CONTEXT_ROBUST}};
101
102 for (std::vector<std::string>::const_iterator flagIter = flagNames.begin(); flagIter != flagNames.end(); ++flagIter)
103 {
104 int ndx;
105 for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
106 {
107 if (*flagIter == s_flagMap[ndx].name)
108 {
109 flags = flags | s_flagMap[ndx].flag;
110 break;
111 }
112 }
113
114 if (ndx == DE_LENGTH_OF_ARRAY(s_flagMap))
115 {
116 tcu::print("ERROR: Unrecognized GL context flag '%s'\n", flagIter->c_str());
117 tcu::print("Supported GL context flags:\n");
118
119 for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
120 tcu::print(" %s\n", s_flagMap[ndx].name);
121
122 throw tcu::NotSupportedError((std::string("Unknown GL context flag '") + *flagIter + "'").c_str(), DE_NULL,
123 __FILE__, __LINE__);
124 }
125 }
126
127 return flags;
128 }
129
createRenderContext(tcu::Platform & platform,const tcu::CommandLine & cmdLine,const RenderConfig & config,const RenderContext * sharedContext)130 RenderContext *createRenderContext(tcu::Platform &platform, const tcu::CommandLine &cmdLine, const RenderConfig &config,
131 const RenderContext *sharedContext)
132 {
133 const ContextFactoryRegistry ®istry = platform.getGLPlatform().getContextFactoryRegistry();
134 const char *factoryName = cmdLine.getGLContextType();
135 const ContextFactory *factory = DE_NULL;
136
137 if (registry.empty())
138 throw tcu::NotSupportedError("OpenGL is not supported", DE_NULL, __FILE__, __LINE__);
139
140 if (factoryName)
141 {
142 factory = registry.getFactoryByName(factoryName);
143
144 if (!factory)
145 {
146 tcu::print("ERROR: Unknown or unsupported GL context type '%s'\n", factoryName);
147 tcu::print("Supported GL context types:\n");
148
149 for (int factoryNdx = 0; factoryNdx < (int)registry.getFactoryCount(); factoryNdx++)
150 {
151 const ContextFactory *curFactory = registry.getFactoryByIndex(factoryNdx);
152 tcu::print(" %s: %s\n", curFactory->getName(), curFactory->getDescription());
153 }
154
155 throw tcu::NotSupportedError((std::string("Unknown GL context type '") + factoryName + "'").c_str(),
156 DE_NULL, __FILE__, __LINE__);
157 }
158 }
159 else
160 factory = registry.getDefaultFactory();
161
162 if (cmdLine.getSurfaceType() == tcu::SURFACETYPE_FBO)
163 {
164 if (sharedContext)
165 TCU_FAIL("Shared context not implemented for FBO surface type");
166 return new FboRenderContext(*factory, config, cmdLine);
167 }
168 else
169 return factory->createContext(config, cmdLine, sharedContext);
170 }
171
createDefaultRenderContext(tcu::Platform & platform,const tcu::CommandLine & cmdLine,ApiType apiType)172 RenderContext *createDefaultRenderContext(tcu::Platform &platform, const tcu::CommandLine &cmdLine, ApiType apiType)
173 {
174 RenderConfig config;
175 ContextFlags ctxFlags = ContextFlags(0);
176
177 if (cmdLine.getGLContextFlags())
178 ctxFlags = parseContextFlags(cmdLine.getGLContextFlags());
179
180 config.type = glu::ContextType(apiType, ctxFlags);
181 parseRenderConfig(&config, cmdLine);
182
183 return createRenderContext(platform, cmdLine, config);
184 }
185
getExtensions(const glw::Functions & gl,ApiType apiType)186 static std::vector<std::string> getExtensions(const glw::Functions &gl, ApiType apiType)
187 {
188 using std::string;
189 using std::vector;
190
191 if (apiType.getProfile() == PROFILE_ES && apiType.getMajorVersion() == 2)
192 {
193 TCU_CHECK(gl.getString);
194
195 const char *extStr = (const char *)gl.getString(GL_EXTENSIONS);
196 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS)");
197
198 if (extStr)
199 return de::splitString(extStr);
200 else
201 throw tcu::TestError("glGetString(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
202 }
203 else
204 {
205 int numExtensions = 0;
206 vector<string> extensions;
207
208 TCU_CHECK(gl.getIntegerv && gl.getStringi);
209
210 gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
211 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS)");
212
213 if (numExtensions > 0)
214 {
215 extensions.resize(numExtensions);
216
217 for (int ndx = 0; ndx < numExtensions; ndx++)
218 {
219 const char *const ext = (const char *)gl.getStringi(GL_EXTENSIONS, ndx);
220 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS)");
221
222 if (ext)
223 extensions[ndx] = ext;
224 else
225 throw tcu::TestError("glGetStringi(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__,
226 __LINE__);
227 }
228 }
229
230 return extensions;
231 }
232 }
233
hasExtension(const glw::Functions & gl,ApiType apiType,const std::string & extension)234 bool hasExtension(const glw::Functions &gl, ApiType apiType, const std::string &extension)
235 {
236 std::vector<std::string> extensions(getExtensions(gl, apiType));
237
238 return de::contains(extensions.begin(), extensions.end(), extension);
239 }
240
initCoreFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)241 void initCoreFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType)
242 {
243 static const struct
244 {
245 ApiType apiType;
246 void (*initFunc)(glw::Functions *gl, const glw::FunctionLoader *loader);
247 } s_initFuncs[] = {
248 {ApiType::es(2, 0), glw::initES20},
249 {ApiType::es(3, 0), glw::initES30},
250 {ApiType::es(3, 1), glw::initES31},
251 {ApiType::es(3, 2), glw::initES32},
252 {ApiType::core(3, 0), glw::initGL30Core},
253 {ApiType::core(3, 1), glw::initGL31Core},
254 {ApiType::core(3, 2), glw::initGL32Core},
255 {ApiType::core(3, 3), glw::initGL33Core},
256 {ApiType::core(4, 0), glw::initGL40Core},
257 {ApiType::core(4, 1), glw::initGL41Core},
258 {ApiType::core(4, 2), glw::initGL42Core},
259 {ApiType::core(4, 3), glw::initGL43Core},
260 {ApiType::core(4, 4), glw::initGL44Core},
261 {ApiType::core(4, 5), glw::initGL45Core},
262 {ApiType::core(4, 6), glw::initGL46Core},
263 // TODO: initialise actual compat functions rather than using core as a dummy
264 {ApiType::compatibility(3, 2), glw::initGL32Core},
265 {ApiType::compatibility(3, 3), glw::initGL33Core},
266 {ApiType::compatibility(4, 0), glw::initGL40Core},
267 {ApiType::compatibility(4, 1), glw::initGL41Core},
268 {ApiType::compatibility(4, 2), glw::initGL42Core},
269 {ApiType::compatibility(4, 3), glw::initGL43Core},
270 {ApiType::compatibility(4, 4), glw::initGL44Core},
271 {ApiType::compatibility(4, 5), glw::initGL45Core},
272 {ApiType::compatibility(4, 6), glw::initGL46Core},
273 };
274
275 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_initFuncs); ndx++)
276 {
277 if (s_initFuncs[ndx].apiType == apiType)
278 {
279 s_initFuncs[ndx].initFunc(dst, loader);
280 return;
281 }
282 }
283
284 throw tcu::InternalError(std::string("Don't know how to load functions for ") + de::toString(apiType));
285 }
286
initExtensionFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)287 void initExtensionFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType)
288 {
289 std::vector<std::string> extensions = getExtensions(*dst, apiType);
290
291 if (!extensions.empty())
292 {
293 std::vector<const char *> extStr(extensions.size());
294
295 for (size_t ndx = 0; ndx < extensions.size(); ndx++)
296 extStr[ndx] = extensions[ndx].c_str();
297
298 initExtensionFunctions(dst, loader, apiType, (int)extStr.size(), &extStr[0]);
299 }
300 }
301
initExtensionFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType,int numExtensions,const char * const * extensions)302 void initExtensionFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType, int numExtensions,
303 const char *const *extensions)
304 {
305 if (apiType.getProfile() == PROFILE_ES)
306 glw::initExtensionsES(dst, loader, numExtensions, extensions);
307 else
308 glw::initExtensionsGL(dst, loader, numExtensions, extensions);
309 }
310
initFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)311 void initFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType)
312 {
313 initCoreFunctions(dst, loader, apiType);
314 initExtensionFunctions(dst, loader, apiType);
315 }
316
getApiTypeDescription(ApiType type)317 const char *getApiTypeDescription(ApiType type)
318 {
319 if (type == glu::ApiType::es(2, 0))
320 return "OpenGL ES 2";
321 else if (type == glu::ApiType::es(3, 0))
322 return "OpenGL ES 3";
323 else if (type == glu::ApiType::es(3, 1))
324 return "OpenGL ES 3.1";
325 else if (type == glu::ApiType::es(3, 2))
326 return "OpenGL ES 3.2";
327 else if (type == glu::ApiType::core(3, 0))
328 return "OpenGL 3.0 core";
329 else if (type == glu::ApiType::core(3, 1))
330 return "OpenGL 3.1 core";
331 else if (type == glu::ApiType::core(3, 2))
332 return "OpenGL 3.2 core";
333 else if (type == glu::ApiType::core(3, 3))
334 return "OpenGL 3.3 core";
335 else if (type == glu::ApiType::core(4, 0))
336 return "OpenGL 4.0 core";
337 else if (type == glu::ApiType::core(4, 1))
338 return "OpenGL 4.1 core";
339 else if (type == glu::ApiType::core(4, 2))
340 return "OpenGL 4.2 core";
341 else if (type == glu::ApiType::core(4, 3))
342 return "OpenGL 4.3 core";
343 else if (type == glu::ApiType::core(4, 4))
344 return "OpenGL 4.4 core";
345 else if (type == glu::ApiType::core(4, 5))
346 return "OpenGL 4.5 core";
347 else if (type == glu::ApiType::core(4, 6))
348 return "OpenGL 4.6 core";
349 else if (type == glu::ApiType::compatibility(3, 2))
350 return "OpenGL 3.2 compatibility";
351 else if (type == glu::ApiType::compatibility(3, 3))
352 return "OpenGL 3.3 compatibility";
353 else if (type == glu::ApiType::compatibility(4, 0))
354 return "OpenGL 4.0 compatibility";
355 else if (type == glu::ApiType::compatibility(4, 1))
356 return "OpenGL 4.1 compatibility";
357 else if (type == glu::ApiType::compatibility(4, 2))
358 return "OpenGL 4.2 compatibility";
359 else if (type == glu::ApiType::compatibility(4, 3))
360 return "OpenGL 4.3 compatibility";
361 else if (type == glu::ApiType::compatibility(4, 4))
362 return "OpenGL 4.4 compatibility";
363 else if (type == glu::ApiType::compatibility(4, 5))
364 return "OpenGL 4.5 compatibility";
365 else if (type == glu::ApiType::compatibility(4, 6))
366 return "OpenGL 4.6 compatibility";
367 else
368 return DE_NULL;
369 }
370
371 } // namespace glu
372