am 7faac846: (-s ours) am c80353d7: am ca5d0d73: Enable clang compilation for mips...
[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 "gluES3PlusWrapperContext.hpp"
28 #include "gluFboRenderContext.hpp"
29 #include "gluPlatform.hpp"
30 #include "gluStrUtil.hpp"
31 #include "glwInitFunctions.hpp"
32 #include "glwEnums.hpp"
33 #include "tcuPlatform.hpp"
34 #include "tcuCommandLine.hpp"
35 #include "deStringUtil.hpp"
36 #include "deSTLUtil.hpp"
37
38 namespace glu
39 {
40
41 inline bool versionGreaterOrEqual (ApiType a, ApiType b)
42 {
43         return a.getMajorVersion() > b.getMajorVersion() ||
44                    (a.getMajorVersion() == b.getMajorVersion() && a.getMinorVersion() >= b.getMinorVersion());
45 }
46
47 bool contextSupports (ContextType ctxType, ApiType requiredApiType)
48 {
49         // \todo [2014-10-06 pyry] Check exact forward-compatible restrictions.
50         const bool forwardCompatible = (ctxType.getFlags() & CONTEXT_FORWARD_COMPATIBLE) != 0;
51
52         if (isContextTypeES(ctxType))
53         {
54                 DE_ASSERT(!forwardCompatible);
55                 return requiredApiType.getProfile() == PROFILE_ES &&
56                            versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
57         }
58         else if (isContextTypeGLCore(ctxType))
59         {
60                 if (forwardCompatible)
61                         return ctxType.getAPI() == requiredApiType;
62                 else
63                         return requiredApiType.getProfile() == PROFILE_CORE &&
64                                    versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
65         }
66         else if (isContextTypeGLCompatibility(ctxType))
67         {
68                 DE_ASSERT(!forwardCompatible);
69                 return (requiredApiType.getProfile() == PROFILE_CORE || requiredApiType.getProfile() == PROFILE_COMPATIBILITY) &&
70                            versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
71         }
72         else
73         {
74                 DE_ASSERT(false);
75                 return false;
76         }
77 }
78
79 static ContextFlags parseContextFlags (const std::string& flagsStr)
80 {
81         const std::vector<std::string>  flagNames       = de::splitString(flagsStr, ',');
82         ContextFlags                                    flags           = ContextFlags(0);
83         static const struct
84         {
85                 const char*             name;
86                 ContextFlags    flag;
87         } s_flagMap[] =
88         {
89                 { "debug",              CONTEXT_DEBUG   },
90                 { "robust",             CONTEXT_ROBUST  }
91         };
92
93         for (std::vector<std::string>::const_iterator flagIter = flagNames.begin(); flagIter != flagNames.end(); ++flagIter)
94         {
95                 int ndx;
96                 for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
97                 {
98                         if (*flagIter == s_flagMap[ndx].name)
99                         {
100                                 flags = flags | s_flagMap[ndx].flag;
101                                 break;
102                         }
103                 }
104
105                 if (ndx == DE_LENGTH_OF_ARRAY(s_flagMap))
106                 {
107                         tcu::print("ERROR: Unrecognized GL context flag '%s'\n", flagIter->c_str());
108                         tcu::print("Supported GL context flags:\n");
109
110                         for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
111                                 tcu::print("  %s\n", s_flagMap[ndx].name);
112
113                         throw tcu::NotSupportedError((std::string("Unknown GL context flag '") + *flagIter + "'").c_str(), DE_NULL, __FILE__, __LINE__);
114                 }
115         }
116
117         return flags;
118 }
119
120 RenderContext* createDefaultRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, ApiType apiType)
121 {
122         const ContextFactoryRegistry&   registry                = platform.getGLPlatform().getContextFactoryRegistry();
123         RenderConfig                                    config;
124         const char*                                             factoryName             = cmdLine.getGLContextType();
125         const ContextFactory*                   factory                 = DE_NULL;
126         ContextFlags                                    ctxFlags                = ContextFlags(0);
127
128         if (registry.empty())
129                 throw tcu::NotSupportedError("OpenGL is not supported", DE_NULL, __FILE__, __LINE__);
130
131         if (cmdLine.getGLContextFlags())
132                 ctxFlags = parseContextFlags(cmdLine.getGLContextFlags());
133
134         config.type = glu::ContextType(apiType, ctxFlags);
135         parseRenderConfig(&config, cmdLine);
136
137         if (factoryName)
138         {
139                 factory = registry.getFactoryByName(factoryName);
140
141                 if (!factory)
142                 {
143                         tcu::print("ERROR: Unknown or unsupported GL context type '%s'\n", factoryName);
144                         tcu::print("Supported GL context types:\n");
145
146                         for (int factoryNdx = 0; factoryNdx < (int)registry.getFactoryCount(); factoryNdx++)
147                         {
148                                 const ContextFactory* curFactory = registry.getFactoryByIndex(factoryNdx);
149                                 tcu::print("  %s: %s\n", curFactory->getName(), curFactory->getDescription());
150                         }
151
152                         throw tcu::NotSupportedError((std::string("Unknown GL context type '") + factoryName + "'").c_str(), DE_NULL, __FILE__, __LINE__);
153                 }
154         }
155         else
156                 factory = registry.getDefaultFactory();
157
158         try
159         {
160                 if (cmdLine.getSurfaceType() == tcu::SURFACETYPE_FBO)
161                         return new FboRenderContext(*factory, config, cmdLine);
162                 else
163                         return factory->createContext(config, cmdLine);
164
165         }
166         catch (const std::exception&)
167         {
168                 // If ES31 context is not available, try using wrapper.
169                 if (config.type.getAPI() == ApiType::es(3,1))
170                 {
171                         tcu::print("Warning: Unable to create native OpenGL ES 3.1 context, will use wrapper context.\n");
172                         return new ES3PlusWrapperContext(*factory, config, cmdLine);
173                 }
174                 else
175                         throw;
176         }
177 }
178
179 static std::vector<std::string> getExtensions (const glw::Functions& gl, ApiType apiType)
180 {
181         using std::vector;
182         using std::string;
183
184         if (apiType.getProfile() == PROFILE_ES && apiType.getMajorVersion() == 2)
185         {
186                 TCU_CHECK(gl.getString);
187
188                 const char*     extStr  = (const char*)gl.getString(GL_EXTENSIONS);
189                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS)");
190
191                 if (extStr)
192                         return de::splitString(extStr);
193                 else
194                         throw tcu::TestError("glGetString(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
195         }
196         else
197         {
198                 int                             numExtensions   = 0;
199                 vector<string>  extensions;
200
201                 TCU_CHECK(gl.getIntegerv && gl.getStringi);
202
203                 gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
204                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS)");
205
206                 if (numExtensions > 0)
207                 {
208                         extensions.resize(numExtensions);
209
210                         for (int ndx = 0; ndx < numExtensions; ndx++)
211                         {
212                                 const char* const ext = (const char*)gl.getStringi(GL_EXTENSIONS, ndx);
213                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS)");
214
215                                 if (ext)
216                                         extensions[ndx] = ext;
217                                 else
218                                         throw tcu::TestError("glGetStringi(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
219                         }
220
221                 }
222
223                 return extensions;
224         }
225 }
226
227 bool hasExtension (const glw::Functions& gl, ApiType apiType, const std::string& extension)
228 {
229         std::vector<std::string> extensions(getExtensions(gl, apiType));
230
231         return de::contains(extensions.begin(), extensions.end(), extension);
232 }
233
234 void initCoreFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
235 {
236         static const struct
237         {
238                 ApiType         apiType;
239                 void            (*initFunc)             (glw::Functions* gl, const glw::FunctionLoader* loader);
240         } s_initFuncs[] =
241         {
242                 { ApiType::es(2,0),             glw::initES20           },
243                 { ApiType::es(3,0),             glw::initES30           },
244                 { ApiType::es(3,1),             glw::initES31           },
245                 { ApiType::core(3,0),   glw::initGL30Core       },
246                 { ApiType::core(3,1),   glw::initGL31Core       },
247                 { ApiType::core(3,2),   glw::initGL32Core       },
248                 { ApiType::core(3,3),   glw::initGL33Core       },
249                 { ApiType::core(4,0),   glw::initGL40Core       },
250                 { ApiType::core(4,1),   glw::initGL41Core       },
251                 { ApiType::core(4,2),   glw::initGL42Core       },
252                 { ApiType::core(4,3),   glw::initGL43Core       },
253                 { ApiType::core(4,4),   glw::initGL44Core       },
254         };
255
256         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_initFuncs); ndx++)
257         {
258                 if (s_initFuncs[ndx].apiType == apiType)
259                 {
260                         s_initFuncs[ndx].initFunc(dst, loader);
261                         return;
262                 }
263         }
264
265         throw tcu::InternalError(std::string("Don't know how to load functions for ") + de::toString(apiType));
266 }
267
268 void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
269 {
270         std::vector<std::string> extensions = getExtensions(*dst, apiType);
271
272         if (!extensions.empty())
273         {
274                 std::vector<const char*> extStr(extensions.size());
275
276                 for (size_t ndx = 0; ndx < extensions.size(); ndx++)
277                         extStr[ndx] = extensions[ndx].c_str();
278
279                 initExtensionFunctions(dst, loader, apiType, (int)extStr.size(), &extStr[0]);
280         }
281 }
282
283 void initExtensionFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType, int numExtensions, const char* const* extensions)
284 {
285         if (apiType.getProfile() == PROFILE_ES)
286                 glw::initExtensionsES(dst, loader, numExtensions, extensions);
287         else
288                 glw::initExtensionsGL(dst, loader, numExtensions, extensions);
289 }
290
291 void initFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
292 {
293         initCoreFunctions(dst, loader, apiType);
294         initExtensionFunctions(dst, loader, apiType);
295 }
296
297 } // glu