Fix texture mip level size in framebuffer fetch tests am: be0d165a5d
[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 // RenderContext
42
43 glw::GenericFuncType RenderContext::getProcAddress (const char*) const
44 {
45         return (glw::GenericFuncType)DE_NULL;
46 }
47
48 void RenderContext::makeCurrent (void)
49 {
50         TCU_THROW(InternalError, "RenderContext::makeCurrent() is not implemented");
51 }
52
53 // Utilities
54
55 inline bool versionGreaterOrEqual (ApiType a, ApiType b)
56 {
57         return a.getMajorVersion() > b.getMajorVersion() ||
58                    (a.getMajorVersion() == b.getMajorVersion() && a.getMinorVersion() >= b.getMinorVersion());
59 }
60
61 bool contextSupports (ContextType ctxType, ApiType requiredApiType)
62 {
63         // \todo [2014-10-06 pyry] Check exact forward-compatible restrictions.
64         const bool forwardCompatible = (ctxType.getFlags() & CONTEXT_FORWARD_COMPATIBLE) != 0;
65
66         if (isContextTypeES(ctxType))
67         {
68                 DE_ASSERT(!forwardCompatible);
69                 return requiredApiType.getProfile() == PROFILE_ES &&
70                            versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
71         }
72         else if (isContextTypeGLCore(ctxType))
73         {
74                 if (forwardCompatible)
75                         return ctxType.getAPI() == requiredApiType;
76                 else
77                         return requiredApiType.getProfile() == PROFILE_CORE &&
78                                    versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
79         }
80         else if (isContextTypeGLCompatibility(ctxType))
81         {
82                 DE_ASSERT(!forwardCompatible);
83                 return (requiredApiType.getProfile() == PROFILE_CORE || requiredApiType.getProfile() == PROFILE_COMPATIBILITY) &&
84                            versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
85         }
86         else
87         {
88                 DE_ASSERT(false);
89                 return false;
90         }
91 }
92
93 static ContextFlags parseContextFlags (const std::string& flagsStr)
94 {
95         const std::vector<std::string>  flagNames       = de::splitString(flagsStr, ',');
96         ContextFlags                                    flags           = ContextFlags(0);
97         static const struct
98         {
99                 const char*             name;
100                 ContextFlags    flag;
101         } s_flagMap[] =
102         {
103                 { "debug",              CONTEXT_DEBUG   },
104                 { "robust",             CONTEXT_ROBUST  }
105         };
106
107         for (std::vector<std::string>::const_iterator flagIter = flagNames.begin(); flagIter != flagNames.end(); ++flagIter)
108         {
109                 int ndx;
110                 for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
111                 {
112                         if (*flagIter == s_flagMap[ndx].name)
113                         {
114                                 flags = flags | s_flagMap[ndx].flag;
115                                 break;
116                         }
117                 }
118
119                 if (ndx == DE_LENGTH_OF_ARRAY(s_flagMap))
120                 {
121                         tcu::print("ERROR: Unrecognized GL context flag '%s'\n", flagIter->c_str());
122                         tcu::print("Supported GL context flags:\n");
123
124                         for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
125                                 tcu::print("  %s\n", s_flagMap[ndx].name);
126
127                         throw tcu::NotSupportedError((std::string("Unknown GL context flag '") + *flagIter + "'").c_str(), DE_NULL, __FILE__, __LINE__);
128                 }
129         }
130
131         return flags;
132 }
133
134 RenderContext* createRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, const RenderConfig& config)
135 {
136         const ContextFactoryRegistry&   registry                = platform.getGLPlatform().getContextFactoryRegistry();
137         const char*                                             factoryName             = cmdLine.getGLContextType();
138         const ContextFactory*                   factory                 = DE_NULL;
139
140         if (registry.empty())
141                 throw tcu::NotSupportedError("OpenGL is not supported", DE_NULL, __FILE__, __LINE__);
142
143         if (factoryName)
144         {
145                 factory = registry.getFactoryByName(factoryName);
146
147                 if (!factory)
148                 {
149                         tcu::print("ERROR: Unknown or unsupported GL context type '%s'\n", factoryName);
150                         tcu::print("Supported GL context types:\n");
151
152                         for (int factoryNdx = 0; factoryNdx < (int)registry.getFactoryCount(); factoryNdx++)
153                         {
154                                 const ContextFactory* curFactory = registry.getFactoryByIndex(factoryNdx);
155                                 tcu::print("  %s: %s\n", curFactory->getName(), curFactory->getDescription());
156                         }
157
158                         throw tcu::NotSupportedError((std::string("Unknown GL context type '") + factoryName + "'").c_str(), DE_NULL, __FILE__, __LINE__);
159                 }
160         }
161         else
162                 factory = registry.getDefaultFactory();
163
164         if (cmdLine.getSurfaceType() == tcu::SURFACETYPE_FBO)
165                 return new FboRenderContext(*factory, config, cmdLine);
166         else
167                 return factory->createContext(config, cmdLine);
168 }
169
170 RenderContext* createDefaultRenderContext (tcu::Platform& platform, const tcu::CommandLine& cmdLine, ApiType apiType)
171 {
172         RenderConfig    config;
173         ContextFlags    ctxFlags        = ContextFlags(0);
174
175         if (cmdLine.getGLContextFlags())
176                 ctxFlags = parseContextFlags(cmdLine.getGLContextFlags());
177
178         config.type = glu::ContextType(apiType, ctxFlags);
179         parseRenderConfig(&config, cmdLine);
180
181         return createRenderContext(platform, cmdLine, config);
182 }
183
184 static std::vector<std::string> getExtensions (const glw::Functions& gl, ApiType apiType)
185 {
186         using std::vector;
187         using std::string;
188
189         if (apiType.getProfile() == PROFILE_ES && apiType.getMajorVersion() == 2)
190         {
191                 TCU_CHECK(gl.getString);
192
193                 const char*     extStr  = (const char*)gl.getString(GL_EXTENSIONS);
194                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS)");
195
196                 if (extStr)
197                         return de::splitString(extStr);
198                 else
199                         throw tcu::TestError("glGetString(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
200         }
201         else
202         {
203                 int                             numExtensions   = 0;
204                 vector<string>  extensions;
205
206                 TCU_CHECK(gl.getIntegerv && gl.getStringi);
207
208                 gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
209                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS)");
210
211                 if (numExtensions > 0)
212                 {
213                         extensions.resize(numExtensions);
214
215                         for (int ndx = 0; ndx < numExtensions; ndx++)
216                         {
217                                 const char* const ext = (const char*)gl.getStringi(GL_EXTENSIONS, ndx);
218                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS)");
219
220                                 if (ext)
221                                         extensions[ndx] = ext;
222                                 else
223                                         throw tcu::TestError("glGetStringi(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
224                         }
225
226                 }
227
228                 return extensions;
229         }
230 }
231
232 bool hasExtension (const glw::Functions& gl, ApiType apiType, const std::string& extension)
233 {
234         std::vector<std::string> extensions(getExtensions(gl, apiType));
235
236         return de::contains(extensions.begin(), extensions.end(), extension);
237 }
238
239 void initCoreFunctions (glw::Functions* dst, const glw::FunctionLoader* loader, ApiType apiType)
240 {
241         static const struct
242         {
243                 ApiType         apiType;
244                 void            (*initFunc)             (glw::Functions* gl, const glw::FunctionLoader* loader);
245         } s_initFuncs[] =
246         {
247                 { ApiType::es(2,0),             glw::initES20           },
248                 { ApiType::es(3,0),             glw::initES30           },
249                 { ApiType::es(3,1),             glw::initES31           },
250                 { ApiType::es(3,2),             glw::initES32           },
251                 { ApiType::core(3,0),   glw::initGL30Core       },
252                 { ApiType::core(3,1),   glw::initGL31Core       },
253                 { ApiType::core(3,2),   glw::initGL32Core       },
254                 { ApiType::core(3,3),   glw::initGL33Core       },
255                 { ApiType::core(4,0),   glw::initGL40Core       },
256                 { ApiType::core(4,1),   glw::initGL41Core       },
257                 { ApiType::core(4,2),   glw::initGL42Core       },
258                 { ApiType::core(4,3),   glw::initGL43Core       },
259                 { ApiType::core(4,4),   glw::initGL44Core       },
260                 { ApiType::core(4,5),   glw::initGL45Core       },
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                                                                            return DE_NULL;
321 }
322
323 } // glu