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