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 329