Vulkan: Add wide-color tests
[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, 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
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
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
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
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
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
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
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
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