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