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 Context Info Class.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "gluContextInfo.hpp"
     25 #include "gluRenderContext.hpp"
     26 #include "gluShaderProgram.hpp"
     27 #include "glwFunctions.hpp"
     28 #include "glwEnums.hpp"
     29 
     30 #include <iterator>
     31 #include <algorithm>
     32 
     33 using std::vector;
     34 using std::string;
     35 using std::set;
     36 
     37 namespace glu
     38 {
     39 
     40 class TryCompileProgram
     41 {
     42 public:
     43 	// \note Assumes that shader pointer can be stored as is (eg. it is static data)
     44 	TryCompileProgram (const char* vertexSource, const char* fragmentSource)
     45 		: m_vertexSource	(vertexSource)
     46 		, m_fragmentSource	(fragmentSource)
     47 	{
     48 	}
     49 
     50 	bool operator() (const RenderContext& context) const
     51 	{
     52 		ShaderProgram program(context,
     53 			ProgramSources() << VertexSource(m_vertexSource)
     54 							 << FragmentSource(m_fragmentSource));
     55 		return program.isOk();
     56 	}
     57 
     58 private:
     59 	const char*	m_vertexSource;
     60 	const char*	m_fragmentSource;
     61 };
     62 
     63 typedef CachedValue<bool, TryCompileProgram> IsProgramSupported;
     64 
     65 // ES2-specific context info
     66 class ES2ContextInfo : public ContextInfo
     67 {
     68 public:
     69 										ES2ContextInfo						(const RenderContext& context);
     70 										~ES2ContextInfo						(void) {}
     71 
     72 	bool								isVertexUniformLoopSupported		(void) const	{ return m_vertexUniformLoopsSupported.getValue(m_context);		}
     73 	bool								isVertexDynamicLoopSupported		(void) const	{ return m_vertexDynamicLoopsSupported.getValue(m_context);		}
     74 	bool								isFragmentHighPrecisionSupported	(void) const	{ return m_fragmentHighPrecisionSupported.getValue(m_context);	}
     75 	bool								isFragmentUniformLoopSupported		(void) const	{ return m_fragmentUniformLoopsSupported.getValue(m_context);	}
     76 	bool								isFragmentDynamicLoopSupported		(void) const	{ return m_fragmentDynamicLoopsSupported.getValue(m_context);	}
     77 
     78 private:
     79 	IsProgramSupported					m_vertexUniformLoopsSupported;
     80 	IsProgramSupported					m_vertexDynamicLoopsSupported;
     81 
     82 	IsProgramSupported					m_fragmentHighPrecisionSupported;
     83 	IsProgramSupported					m_fragmentUniformLoopsSupported;
     84 	IsProgramSupported					m_fragmentDynamicLoopsSupported;
     85 };
     86 
     87 static const char* s_defaultVertexShader =
     88 	"attribute highp vec4 a_position;\n"
     89 	"void main (void) {\n"
     90 	"	gl_Position = a_position;\n"
     91 	"}\n";
     92 static const char* s_defaultFragmentShader =
     93 	"void main (void) {\n"
     94 	"	gl_FragColor = vec4(1.0);\n"
     95 	"}\n";
     96 
     97 static const char* s_vertexUniformLoopsSupported =
     98 	"attribute highp vec4	a_position;\n"
     99 	"uniform int			u_numIters;\n"
    100 	"void main (void) {\n"
    101 	"	gl_Position = a_position;\n"
    102 	"	for (int i = 0; i < u_numIters; i++)\n"
    103 	"		gl_Position += vec4(0.1);\n"
    104 	"}\n";
    105 static const char* s_vertexDynamicLoopsSupported =
    106 	"attribute highp vec4	a_position;\n"
    107 	"uniform mediump float	a, b;\n"
    108 	"void main (void) {\n"
    109 	"	gl_Position = a_position;\n"
    110 	"	int numIters = a < b ? int(3.0*b) : int(a_position.x);\n"
    111 	"	for (int i = 0; i < numIters; i++)\n"
    112 	"		gl_Position += vec4(0.1);\n"
    113 	"}\n";
    114 
    115 static const char* s_fragmentHighPrecisionSupported =
    116 	"varying highp vec4		v_color;\n"
    117 	"void main (void) {\n"
    118 	"	highp float tmp = v_color.r;\n"
    119 	"	gl_FragColor = v_color;\n"
    120 	"}\n";
    121 static const char* s_fragmentUniformLoopsSupported =
    122 	"varying mediump vec4	v_color;\n"
    123 	"uniform int			u_numIters;\n"
    124 	"void main (void) {\n"
    125 	"	gl_FragColor = v_color;\n"
    126 	"	for (int i = 0; i < u_numIters; i++)\n"
    127 	"		gl_FragColor += vec4(0.1);\n"
    128 	"}\n";
    129 static const char* s_fragmentDynamicLoopsSupported =
    130 	"varying mediump vec4	v_color;\n"
    131 	"uniform mediump float	a, b;\n"
    132 	"void main (void) {\n"
    133 	"	gl_FragColor = v_color;\n"
    134 	"	int numIters = a < b ? int(3.0*b) : int(v_color.x);\n"
    135 	"	for (int i = 0; i < numIters; i++)\n"
    136 	"		gl_FragColor += vec4(0.1);\n"
    137 	"}\n";
    138 
    139 ES2ContextInfo::ES2ContextInfo (const RenderContext& context)
    140 	: glu::ContextInfo					(context)
    141 	, m_vertexUniformLoopsSupported		(TryCompileProgram(s_vertexUniformLoopsSupported, s_defaultFragmentShader))
    142 	, m_vertexDynamicLoopsSupported		(TryCompileProgram(s_vertexDynamicLoopsSupported, s_defaultFragmentShader))
    143 	, m_fragmentHighPrecisionSupported	(TryCompileProgram(s_defaultVertexShader, s_fragmentHighPrecisionSupported))
    144 	, m_fragmentUniformLoopsSupported	(TryCompileProgram(s_defaultVertexShader, s_fragmentUniformLoopsSupported))
    145 	, m_fragmentDynamicLoopsSupported	(TryCompileProgram(s_defaultVertexShader, s_fragmentDynamicLoopsSupported))
    146 {
    147 }
    148 
    149 static void split (vector<string>& dst, const string& src)
    150 {
    151 	size_t start = 0;
    152 	size_t end	 = string::npos;
    153 
    154 	while ((end = src.find(' ', start)) != string::npos)
    155 	{
    156 		dst.push_back(src.substr(start, end-start));
    157 		start = end+1;
    158 	}
    159 
    160 	if (start < end)
    161 		dst.push_back(src.substr(start, end-start));
    162 }
    163 
    164 vector<string> GetExtensions::operator() (const RenderContext& context) const
    165 {
    166 	const glw::Functions& gl = context.getFunctions();
    167 
    168 	if (context.getType().getAPI() == ApiType::es(2,0))
    169 	{
    170 		const char* result = (const char*)gl.getString(GL_EXTENSIONS);
    171 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS) failed");
    172 
    173 		vector<string> extensions;
    174 		split(extensions, string(result));
    175 
    176 		return extensions;
    177 	}
    178 	else
    179 	{
    180 		int				numExtensions	= 0;
    181 		vector<string>	extensions;
    182 
    183 		gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
    184 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS) failed");
    185 
    186 		extensions.resize(numExtensions);
    187 		for (int ndx = 0; ndx < numExtensions; ndx++)
    188 			extensions[ndx] = (const char*)gl.getStringi(GL_EXTENSIONS, ndx);
    189 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS, ndx) failed");
    190 
    191 		return extensions;
    192 	}
    193 }
    194 
    195 set<int> GetCompressedTextureFormats::operator() (const RenderContext& context) const
    196 {
    197 	const glw::Functions& gl = context.getFunctions();
    198 
    199 	int numFormats = 0;
    200 	gl.getIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
    201 
    202 	vector<int> formats(numFormats);
    203 	if (numFormats > 0)
    204 		gl.getIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, &formats[0]);
    205 
    206 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS) failed");
    207 
    208 	set<int> formatSet;
    209 	std::copy(formats.begin(), formats.end(), std::inserter(formatSet, formatSet.begin()));
    210 
    211 	return formatSet;
    212 }
    213 
    214 // ContextInfo
    215 
    216 ContextInfo::ContextInfo (const RenderContext& context)
    217 	: m_context(context)
    218 {
    219 }
    220 
    221 ContextInfo::~ContextInfo (void)
    222 {
    223 }
    224 
    225 int ContextInfo::getInt (int param) const
    226 {
    227 	int val = -1;
    228 	m_context.getFunctions().getIntegerv(param, &val);
    229 	GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetIntegerv() failed");
    230 	return val;
    231 }
    232 
    233 bool ContextInfo::getBool (int param) const
    234 {
    235 	glw::GLboolean val = GL_FALSE;
    236 	m_context.getFunctions().getBooleanv(param, &val);
    237 	GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetBooleanv() failed");
    238 	return val != GL_FALSE;
    239 }
    240 
    241 const char* ContextInfo::getString (int param) const
    242 {
    243 	const char* str = (const char*)m_context.getFunctions().getString(param);
    244 	GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetString() failed");
    245 	return str;
    246 }
    247 
    248 bool ContextInfo::isCompressedTextureFormatSupported (int format) const
    249 {
    250 	const set<int>& formats = m_compressedTextureFormats.getValue(m_context);
    251 	return formats.find(format) != formats.end();
    252 }
    253 
    254 bool ContextInfo::isExtensionSupported (const char* name) const
    255 {
    256 	const std::vector<std::string>& extensions = getExtensions();
    257 	return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
    258 }
    259 
    260 ContextInfo* ContextInfo::create (const RenderContext& context)
    261 {
    262 	// ES2 uses special variant that checks support for various shader features
    263 	// by trying to compile shader programs.
    264 	if (context.getType().getAPI() == ApiType::es(2,0))
    265 		return new ES2ContextInfo(context);
    266 
    267 	return new ContextInfo(context);
    268 }
    269 
    270 } // glu
    271