Home | History | Annotate | Download | only in opengl
      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