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 };
266
267 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_initFuncs); ndx++)
268 {
269 if (s_initFuncs[ndx].apiType == apiType)
270 {
271 s_initFuncs[ndx].initFunc(dst, loader);
272 return;
273 }
274 }
275
276 throw tcu::InternalError(std::string("Don't know how to load functions for ") + de::toString(apiType));
277 }
278
initExtensionFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)279 void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
280 {
281 std::vector<std::string> extensions = getExtensions(*dst, apiType);
282
283 if (!extensions.empty())
284 {
285 std::vector<const char*> extStr(extensions.size());
286
287 for (size_t ndx = 0; ndx < extensions.size(); ndx++)
288 extStr[ndx] = extensions[ndx].c_str();
289
290 initExtensionFunctions(dst, loader, apiType, (int)extStr.size(), &extStr[0]);
291 }
292 }
293
initExtensionFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType,int numExtensions,const char * const * extensions)294 void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType, int numExtensions, const char* const* extensions)
295 {
296 if (apiType.getProfile() == PROFILE_ES)
297 glw::initExtensionsES(dst, loader, numExtensions, extensions);
298 else
299 glw::initExtensionsGL(dst, loader, numExtensions, extensions);
300 }
301
initFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)302 void initFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
303 {
304 initCoreFunctions(dst, loader, apiType);
305 initExtensionFunctions(dst, loader, apiType);
306 }
307
getApiTypeDescription(ApiType type)308 const char* getApiTypeDescription (ApiType type)
309 {
310 if (type == glu::ApiType::es(2, 0)) return "OpenGL ES 2";
311 else if (type == glu::ApiType::es(3, 0)) return "OpenGL ES 3";
312 else if (type == glu::ApiType::es(3, 1)) return "OpenGL ES 3.1";
313 else if (type == glu::ApiType::es(3, 2)) return "OpenGL ES 3.2";
314 else if (type == glu::ApiType::core(3, 0)) return "OpenGL 3.0 core";
315 else if (type == glu::ApiType::core(3, 1)) return "OpenGL 3.1 core";
316 else if (type == glu::ApiType::core(3, 2)) return "OpenGL 3.2 core";
317 else if (type == glu::ApiType::core(3, 3)) return "OpenGL 3.3 core";
318 else if (type == glu::ApiType::core(4, 0)) return "OpenGL 4.0 core";
319 else if (type == glu::ApiType::core(4, 1)) return "OpenGL 4.1 core";
320 else if (type == glu::ApiType::core(4, 2)) return "OpenGL 4.2 core";
321 else if (type == glu::ApiType::core(4, 3)) return "OpenGL 4.3 core";
322 else if (type == glu::ApiType::core(4, 4)) return "OpenGL 4.4 core";
323 else if (type == glu::ApiType::core(4, 5)) return "OpenGL 4.5 core";
324 else if (type == glu::ApiType::core(4, 6)) return "OpenGL 4.6 core";
325 else return DE_NULL;
326 }
327
328 } // glu
329