Merge vk-gl-cts/opengl-es-cts-3.2.4 into vk-gl-cts/master
[platform/upstream/VK-GL-CTS.git] / framework / opengl / gluRenderContext.cpp
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
42 glw::GenericFuncType RenderContext::getProcAddress (const char*) const
43 {
44         return (glw::GenericFuncType)DE_NULL;
45 }
46
47 void RenderContext::makeCurrent (void)
48 {
49         TCU_THROW(InternalError, "RenderContext::makeCurrent() is not implemented");
50 }
51
52 // Utilities
53
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
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
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
133 RenderContext* createRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, const RenderConfig& config)
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                 return new FboRenderContext(*factory, config, cmdLine);
165         else
166                 return factory->createContext(config, cmdLine);
167 }
168
169 RenderContext* createDefaultRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, ApiType apiType)
170 {
171         RenderConfig    config;
172         ContextFlags    ctxFlags        = ContextFlags(0);
173
174         if (cmdLine.getGLContextFlags())
175                 ctxFlags = parseContextFlags(cmdLine.getGLContextFlags());
176
177         config.type = glu::ContextType(apiType, ctxFlags);
178         parseRenderConfig(&config, cmdLine);
179
180         return createRenderContext(platform, cmdLine, config);
181 }
182
183 static std::vector<std::string> getExtensions (const glw::Functions& gl, ApiType apiType)
184 {
185         using std::vector;
186         using std::string;
187
188         if (apiType.getProfile() == PROFILE_ES && apiType.getMajorVersion() == 2)
189         {
190                 TCU_CHECK(gl.getString);
191
192                 const char*     extStr  = (const char*)gl.getString(GL_EXTENSIONS);
193                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS)");
194
195                 if (extStr)
196                         return de::splitString(extStr);
197                 else
198                         throw tcu::TestError("glGetString(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
199         }
200         else
201         {
202                 int                             numExtensions   = 0;
203                 vector<string>  extensions;
204
205                 TCU_CHECK(gl.getIntegerv && gl.getStringi);
206
207                 gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
208                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS)");
209
210                 if (numExtensions > 0)
211                 {
212                         extensions.resize(numExtensions);
213
214                         for (int ndx = 0; ndx < numExtensions; ndx++)
215                         {
216                                 const char* const ext = (const char*)gl.getStringi(GL_EXTENSIONS, ndx);
217                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS)");
218
219                                 if (ext)
220                                         extensions[ndx] = ext;
221                                 else
222                                         throw tcu::TestError("glGetStringi(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
223                         }
224
225                 }
226
227                 return extensions;
228         }
229 }
230
231 bool hasExtension (const glw::Functions& gl, ApiType apiType, const std::string& extension)
232 {
233         std::vector<std::string> extensions(getExtensions(gl, apiType));
234
235         return de::contains(extensions.begin(), extensions.end(), extension);
236 }
237
238 void initCoreFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
239 {
240         static const struct
241         {
242                 ApiType         apiType;
243                 void            (*initFunc)             (glw::Functions* gl, const glw::FunctionLoader* loader);
244         } s_initFuncs[] =
245         {
246                 { ApiType::es(2,0),             glw::initES20           },
247                 { ApiType::es(3,0),             glw::initES30           },
248                 { ApiType::es(3,1),             glw::initES31           },
249                 { ApiType::es(3,2),             glw::initES32           },
250                 { ApiType::core(3,0),   glw::initGL30Core       },
251                 { ApiType::core(3,1),   glw::initGL31Core       },
252                 { ApiType::core(3,2),   glw::initGL32Core       },
253                 { ApiType::core(3,3),   glw::initGL33Core       },
254                 { ApiType::core(4,0),   glw::initGL40Core       },
255                 { ApiType::core(4,1),   glw::initGL41Core       },
256                 { ApiType::core(4,2),   glw::initGL42Core       },
257                 { ApiType::core(4,3),   glw::initGL43Core       },
258                 { ApiType::core(4,4),   glw::initGL44Core       },
259                 { ApiType::core(4,5),   glw::initGL45Core       },
260                 { ApiType::core(4,6),   glw::initGL46Core       },
261         };
262
263         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_initFuncs); ndx++)
264         {
265                 if (s_initFuncs[ndx].apiType == apiType)
266                 {
267                         s_initFuncs[ndx].initFunc(dst, loader);
268                         return;
269                 }
270         }
271
272         throw tcu::InternalError(std::string("Don't know how to load functions for ") + de::toString(apiType));
273 }
274
275 void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
276 {
277         std::vector<std::string> extensions = getExtensions(*dst, apiType);
278
279         if (!extensions.empty())
280         {
281                 std::vector<const char*> extStr(extensions.size());
282
283                 for (size_t ndx = 0; ndx < extensions.size(); ndx++)
284                         extStr[ndx] = extensions[ndx].c_str();
285
286                 initExtensionFunctions(dst, loader, apiType, (int)extStr.size(), &extStr[0]);
287         }
288 }
289
290 void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType, int numExtensions, const char* const* extensions)
291 {
292         if (apiType.getProfile() == PROFILE_ES)
293                 glw::initExtensionsES(dst, loader, numExtensions, extensions);
294         else
295                 glw::initExtensionsGL(dst, loader, numExtensions, extensions);
296 }
297
298 void initFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
299 {
300         initCoreFunctions(dst, loader, apiType);
301         initExtensionFunctions(dst, loader, apiType);
302 }
303
304 const char* getApiTypeDescription (ApiType type)
305 {
306         if (type == glu::ApiType::es(2, 0))                     return "OpenGL ES 2";
307         else if (type == glu::ApiType::es(3, 0))        return "OpenGL ES 3";
308         else if (type == glu::ApiType::es(3, 1))        return "OpenGL ES 3.1";
309         else if (type == glu::ApiType::es(3, 2))        return "OpenGL ES 3.2";
310         else if (type == glu::ApiType::core(3, 0))      return "OpenGL 3.0 core";
311         else if (type == glu::ApiType::core(3, 1))      return "OpenGL 3.1 core";
312         else if (type == glu::ApiType::core(3, 2))      return "OpenGL 3.2 core";
313         else if (type == glu::ApiType::core(3, 3))      return "OpenGL 3.3 core";
314         else if (type == glu::ApiType::core(4, 0))      return "OpenGL 4.0 core";
315         else if (type == glu::ApiType::core(4, 1))      return "OpenGL 4.1 core";
316         else if (type == glu::ApiType::core(4, 2))      return "OpenGL 4.2 core";
317         else if (type == glu::ApiType::core(4, 3))      return "OpenGL 4.3 core";
318         else if (type == glu::ApiType::core(4, 4))      return "OpenGL 4.4 core";
319         else if (type == glu::ApiType::core(4, 5))      return "OpenGL 4.5 core";
320         else if (type == glu::ApiType::core(4, 6))      return "OpenGL 4.6 core";
321         else                                                                            return DE_NULL;
322 }
323
324 } // glu