xref: /aosp_15_r20/external/deqp/framework/opengl/gluRenderContext.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 && versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
69     }
70     else if (isContextTypeGLCore(ctxType))
71     {
72         if (forwardCompatible)
73             return ctxType.getAPI() == requiredApiType;
74         else
75             return requiredApiType.getProfile() == PROFILE_CORE &&
76                    versionGreaterOrEqual(ctxType.getAPI(), requiredApiType);
77     }
78     else if (isContextTypeGLCompatibility(ctxType))
79     {
80         DE_ASSERT(!forwardCompatible);
81         return (requiredApiType.getProfile() == PROFILE_CORE ||
82                 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[] = {{"debug", CONTEXT_DEBUG}, {"robust", CONTEXT_ROBUST}};
101 
102     for (std::vector<std::string>::const_iterator flagIter = flagNames.begin(); flagIter != flagNames.end(); ++flagIter)
103     {
104         int ndx;
105         for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
106         {
107             if (*flagIter == s_flagMap[ndx].name)
108             {
109                 flags = flags | s_flagMap[ndx].flag;
110                 break;
111             }
112         }
113 
114         if (ndx == DE_LENGTH_OF_ARRAY(s_flagMap))
115         {
116             tcu::print("ERROR: Unrecognized GL context flag '%s'\n", flagIter->c_str());
117             tcu::print("Supported GL context flags:\n");
118 
119             for (ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_flagMap); ndx++)
120                 tcu::print("  %s\n", s_flagMap[ndx].name);
121 
122             throw tcu::NotSupportedError((std::string("Unknown GL context flag '") + *flagIter + "'").c_str(), DE_NULL,
123                                          __FILE__, __LINE__);
124         }
125     }
126 
127     return flags;
128 }
129 
createRenderContext(tcu::Platform & platform,const tcu::CommandLine & cmdLine,const RenderConfig & config,const RenderContext * sharedContext)130 RenderContext *createRenderContext(tcu::Platform &platform, const tcu::CommandLine &cmdLine, const RenderConfig &config,
131                                    const RenderContext *sharedContext)
132 {
133     const ContextFactoryRegistry &registry = platform.getGLPlatform().getContextFactoryRegistry();
134     const char *factoryName                = cmdLine.getGLContextType();
135     const ContextFactory *factory          = DE_NULL;
136 
137     if (registry.empty())
138         throw tcu::NotSupportedError("OpenGL is not supported", DE_NULL, __FILE__, __LINE__);
139 
140     if (factoryName)
141     {
142         factory = registry.getFactoryByName(factoryName);
143 
144         if (!factory)
145         {
146             tcu::print("ERROR: Unknown or unsupported GL context type '%s'\n", factoryName);
147             tcu::print("Supported GL context types:\n");
148 
149             for (int factoryNdx = 0; factoryNdx < (int)registry.getFactoryCount(); factoryNdx++)
150             {
151                 const ContextFactory *curFactory = registry.getFactoryByIndex(factoryNdx);
152                 tcu::print("  %s: %s\n", curFactory->getName(), curFactory->getDescription());
153             }
154 
155             throw tcu::NotSupportedError((std::string("Unknown GL context type '") + factoryName + "'").c_str(),
156                                          DE_NULL, __FILE__, __LINE__);
157         }
158     }
159     else
160         factory = registry.getDefaultFactory();
161 
162     if (cmdLine.getSurfaceType() == tcu::SURFACETYPE_FBO)
163     {
164         if (sharedContext)
165             TCU_FAIL("Shared context not implemented for  FBO surface type");
166         return new FboRenderContext(*factory, config, cmdLine);
167     }
168     else
169         return factory->createContext(config, cmdLine, sharedContext);
170 }
171 
createDefaultRenderContext(tcu::Platform & platform,const tcu::CommandLine & cmdLine,ApiType apiType)172 RenderContext *createDefaultRenderContext(tcu::Platform &platform, const tcu::CommandLine &cmdLine, ApiType apiType)
173 {
174     RenderConfig config;
175     ContextFlags ctxFlags = ContextFlags(0);
176 
177     if (cmdLine.getGLContextFlags())
178         ctxFlags = parseContextFlags(cmdLine.getGLContextFlags());
179 
180     config.type = glu::ContextType(apiType, ctxFlags);
181     parseRenderConfig(&config, cmdLine);
182 
183     return createRenderContext(platform, cmdLine, config);
184 }
185 
getExtensions(const glw::Functions & gl,ApiType apiType)186 static std::vector<std::string> getExtensions(const glw::Functions &gl, ApiType apiType)
187 {
188     using std::string;
189     using std::vector;
190 
191     if (apiType.getProfile() == PROFILE_ES && apiType.getMajorVersion() == 2)
192     {
193         TCU_CHECK(gl.getString);
194 
195         const char *extStr = (const char *)gl.getString(GL_EXTENSIONS);
196         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS)");
197 
198         if (extStr)
199             return de::splitString(extStr);
200         else
201             throw tcu::TestError("glGetString(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__, __LINE__);
202     }
203     else
204     {
205         int numExtensions = 0;
206         vector<string> extensions;
207 
208         TCU_CHECK(gl.getIntegerv && gl.getStringi);
209 
210         gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
211         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS)");
212 
213         if (numExtensions > 0)
214         {
215             extensions.resize(numExtensions);
216 
217             for (int ndx = 0; ndx < numExtensions; ndx++)
218             {
219                 const char *const ext = (const char *)gl.getStringi(GL_EXTENSIONS, ndx);
220                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS)");
221 
222                 if (ext)
223                     extensions[ndx] = ext;
224                 else
225                     throw tcu::TestError("glGetStringi(GL_EXTENSIONS) returned null pointer", DE_NULL, __FILE__,
226                                          __LINE__);
227             }
228         }
229 
230         return extensions;
231     }
232 }
233 
hasExtension(const glw::Functions & gl,ApiType apiType,const std::string & extension)234 bool hasExtension(const glw::Functions &gl, ApiType apiType, const std::string &extension)
235 {
236     std::vector<std::string> extensions(getExtensions(gl, apiType));
237 
238     return de::contains(extensions.begin(), extensions.end(), extension);
239 }
240 
initCoreFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)241 void initCoreFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType)
242 {
243     static const struct
244     {
245         ApiType apiType;
246         void (*initFunc)(glw::Functions *gl, const glw::FunctionLoader *loader);
247     } s_initFuncs[] = {
248         {ApiType::es(2, 0), glw::initES20},
249         {ApiType::es(3, 0), glw::initES30},
250         {ApiType::es(3, 1), glw::initES31},
251         {ApiType::es(3, 2), glw::initES32},
252         {ApiType::core(3, 0), glw::initGL30Core},
253         {ApiType::core(3, 1), glw::initGL31Core},
254         {ApiType::core(3, 2), glw::initGL32Core},
255         {ApiType::core(3, 3), glw::initGL33Core},
256         {ApiType::core(4, 0), glw::initGL40Core},
257         {ApiType::core(4, 1), glw::initGL41Core},
258         {ApiType::core(4, 2), glw::initGL42Core},
259         {ApiType::core(4, 3), glw::initGL43Core},
260         {ApiType::core(4, 4), glw::initGL44Core},
261         {ApiType::core(4, 5), glw::initGL45Core},
262         {ApiType::core(4, 6), glw::initGL46Core},
263         // TODO: initialise actual compat functions rather than using core as a dummy
264         {ApiType::compatibility(3, 2), glw::initGL32Core},
265         {ApiType::compatibility(3, 3), glw::initGL33Core},
266         {ApiType::compatibility(4, 0), glw::initGL40Core},
267         {ApiType::compatibility(4, 1), glw::initGL41Core},
268         {ApiType::compatibility(4, 2), glw::initGL42Core},
269         {ApiType::compatibility(4, 3), glw::initGL43Core},
270         {ApiType::compatibility(4, 4), glw::initGL44Core},
271         {ApiType::compatibility(4, 5), glw::initGL45Core},
272         {ApiType::compatibility(4, 6), glw::initGL46Core},
273     };
274 
275     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_initFuncs); ndx++)
276     {
277         if (s_initFuncs[ndx].apiType == apiType)
278         {
279             s_initFuncs[ndx].initFunc(dst, loader);
280             return;
281         }
282     }
283 
284     throw tcu::InternalError(std::string("Don't know how to load functions for ") + de::toString(apiType));
285 }
286 
initExtensionFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)287 void initExtensionFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType)
288 {
289     std::vector<std::string> extensions = getExtensions(*dst, apiType);
290 
291     if (!extensions.empty())
292     {
293         std::vector<const char *> extStr(extensions.size());
294 
295         for (size_t ndx = 0; ndx < extensions.size(); ndx++)
296             extStr[ndx] = extensions[ndx].c_str();
297 
298         initExtensionFunctions(dst, loader, apiType, (int)extStr.size(), &extStr[0]);
299     }
300 }
301 
initExtensionFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType,int numExtensions,const char * const * extensions)302 void initExtensionFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType, int numExtensions,
303                             const char *const *extensions)
304 {
305     if (apiType.getProfile() == PROFILE_ES)
306         glw::initExtensionsES(dst, loader, numExtensions, extensions);
307     else
308         glw::initExtensionsGL(dst, loader, numExtensions, extensions);
309 }
310 
initFunctions(glw::Functions * dst,const glw::FunctionLoader * loader,ApiType apiType)311 void initFunctions(glw::Functions *dst, const glw::FunctionLoader *loader, ApiType apiType)
312 {
313     initCoreFunctions(dst, loader, apiType);
314     initExtensionFunctions(dst, loader, apiType);
315 }
316 
getApiTypeDescription(ApiType type)317 const char *getApiTypeDescription(ApiType type)
318 {
319     if (type == glu::ApiType::es(2, 0))
320         return "OpenGL ES 2";
321     else if (type == glu::ApiType::es(3, 0))
322         return "OpenGL ES 3";
323     else if (type == glu::ApiType::es(3, 1))
324         return "OpenGL ES 3.1";
325     else if (type == glu::ApiType::es(3, 2))
326         return "OpenGL ES 3.2";
327     else if (type == glu::ApiType::core(3, 0))
328         return "OpenGL 3.0 core";
329     else if (type == glu::ApiType::core(3, 1))
330         return "OpenGL 3.1 core";
331     else if (type == glu::ApiType::core(3, 2))
332         return "OpenGL 3.2 core";
333     else if (type == glu::ApiType::core(3, 3))
334         return "OpenGL 3.3 core";
335     else if (type == glu::ApiType::core(4, 0))
336         return "OpenGL 4.0 core";
337     else if (type == glu::ApiType::core(4, 1))
338         return "OpenGL 4.1 core";
339     else if (type == glu::ApiType::core(4, 2))
340         return "OpenGL 4.2 core";
341     else if (type == glu::ApiType::core(4, 3))
342         return "OpenGL 4.3 core";
343     else if (type == glu::ApiType::core(4, 4))
344         return "OpenGL 4.4 core";
345     else if (type == glu::ApiType::core(4, 5))
346         return "OpenGL 4.5 core";
347     else if (type == glu::ApiType::core(4, 6))
348         return "OpenGL 4.6 core";
349     else if (type == glu::ApiType::compatibility(3, 2))
350         return "OpenGL 3.2 compatibility";
351     else if (type == glu::ApiType::compatibility(3, 3))
352         return "OpenGL 3.3 compatibility";
353     else if (type == glu::ApiType::compatibility(4, 0))
354         return "OpenGL 4.0 compatibility";
355     else if (type == glu::ApiType::compatibility(4, 1))
356         return "OpenGL 4.1 compatibility";
357     else if (type == glu::ApiType::compatibility(4, 2))
358         return "OpenGL 4.2 compatibility";
359     else if (type == glu::ApiType::compatibility(4, 3))
360         return "OpenGL 4.3 compatibility";
361     else if (type == glu::ApiType::compatibility(4, 4))
362         return "OpenGL 4.4 compatibility";
363     else if (type == glu::ApiType::compatibility(4, 5))
364         return "OpenGL 4.5 compatibility";
365     else if (type == glu::ApiType::compatibility(4, 6))
366         return "OpenGL 4.6 compatibility";
367     else
368         return DE_NULL;
369 }
370 
371 } // namespace glu
372