• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
TryCompileProgram(const char * vertexSource,const char * fragmentSource)44 	TryCompileProgram (const char* vertexSource, const char* fragmentSource)
45 		: m_vertexSource	(vertexSource)
46 		, m_fragmentSource	(fragmentSource)
47 	{
48 	}
49 
operator ()(const RenderContext & context) const50 	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 
IsES3Compatible(const glw::Functions & gl)65 bool IsES3Compatible(const glw::Functions& gl)
66 {
67 	// Detect compatible GLES context by querying GL_MAJOR_VERSION.
68 	// This query does not exist on GLES2 so succeeding query implies GLES3+ context.
69 	glw::GLint majorVersion = 0;
70 	gl.getError();
71 	gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
72 
73 	return (gl.getError() == GL_NO_ERROR);
74 }
75 
76 // ES2-specific context info
77 class ES2ContextInfo : public ContextInfo
78 {
79 public:
80 										ES2ContextInfo						(const RenderContext& context);
~ES2ContextInfo(void)81 										~ES2ContextInfo						(void) {}
82 
isVertexUniformLoopSupported(void) const83 	bool								isVertexUniformLoopSupported		(void) const	{ return m_vertexUniformLoopsSupported.getValue(m_context);		}
isVertexDynamicLoopSupported(void) const84 	bool								isVertexDynamicLoopSupported		(void) const	{ return m_vertexDynamicLoopsSupported.getValue(m_context);		}
isFragmentHighPrecisionSupported(void) const85 	bool								isFragmentHighPrecisionSupported	(void) const	{ return m_fragmentHighPrecisionSupported.getValue(m_context);	}
isFragmentUniformLoopSupported(void) const86 	bool								isFragmentUniformLoopSupported		(void) const	{ return m_fragmentUniformLoopsSupported.getValue(m_context);	}
isFragmentDynamicLoopSupported(void) const87 	bool								isFragmentDynamicLoopSupported		(void) const	{ return m_fragmentDynamicLoopsSupported.getValue(m_context);	}
88 
89 private:
90 	IsProgramSupported					m_vertexUniformLoopsSupported;
91 	IsProgramSupported					m_vertexDynamicLoopsSupported;
92 
93 	IsProgramSupported					m_fragmentHighPrecisionSupported;
94 	IsProgramSupported					m_fragmentUniformLoopsSupported;
95 	IsProgramSupported					m_fragmentDynamicLoopsSupported;
96 };
97 
98 static const char* s_defaultVertexShader =
99 	"attribute highp vec4 a_position;\n"
100 	"void main (void) {\n"
101 	"	gl_Position = a_position;\n"
102 	"}\n";
103 static const char* s_defaultFragmentShader =
104 	"void main (void) {\n"
105 	"	gl_FragColor = vec4(1.0);\n"
106 	"}\n";
107 
108 static const char* s_vertexUniformLoopsSupported =
109 	"attribute highp vec4	a_position;\n"
110 	"uniform int			u_numIters;\n"
111 	"void main (void) {\n"
112 	"	gl_Position = a_position;\n"
113 	"	for (int i = 0; i < u_numIters; i++)\n"
114 	"		gl_Position += vec4(0.1);\n"
115 	"}\n";
116 static const char* s_vertexDynamicLoopsSupported =
117 	"attribute highp vec4	a_position;\n"
118 	"uniform mediump float	a, b;\n"
119 	"void main (void) {\n"
120 	"	gl_Position = a_position;\n"
121 	"	int numIters = a < b ? int(3.0*b) : int(a_position.x);\n"
122 	"	for (int i = 0; i < numIters; i++)\n"
123 	"		gl_Position += vec4(0.1);\n"
124 	"}\n";
125 
126 static const char* s_fragmentHighPrecisionSupported =
127 	"varying highp vec4		v_color;\n"
128 	"void main (void) {\n"
129 	"	highp float tmp = v_color.r;\n"
130 	"	gl_FragColor = v_color;\n"
131 	"}\n";
132 static const char* s_fragmentUniformLoopsSupported =
133 	"varying mediump vec4	v_color;\n"
134 	"uniform int			u_numIters;\n"
135 	"void main (void) {\n"
136 	"	gl_FragColor = v_color;\n"
137 	"	for (int i = 0; i < u_numIters; i++)\n"
138 	"		gl_FragColor += vec4(0.1);\n"
139 	"}\n";
140 static const char* s_fragmentDynamicLoopsSupported =
141 	"varying mediump vec4	v_color;\n"
142 	"uniform mediump float	a, b;\n"
143 	"void main (void) {\n"
144 	"	gl_FragColor = v_color;\n"
145 	"	int numIters = a < b ? int(3.0*b) : int(v_color.x);\n"
146 	"	for (int i = 0; i < numIters; i++)\n"
147 	"		gl_FragColor += vec4(0.1);\n"
148 	"}\n";
149 
ES2ContextInfo(const RenderContext & context)150 ES2ContextInfo::ES2ContextInfo (const RenderContext& context)
151 	: glu::ContextInfo					(context)
152 	, m_vertexUniformLoopsSupported		(TryCompileProgram(s_vertexUniformLoopsSupported, s_defaultFragmentShader))
153 	, m_vertexDynamicLoopsSupported		(TryCompileProgram(s_vertexDynamicLoopsSupported, s_defaultFragmentShader))
154 	, m_fragmentHighPrecisionSupported	(TryCompileProgram(s_defaultVertexShader, s_fragmentHighPrecisionSupported))
155 	, m_fragmentUniformLoopsSupported	(TryCompileProgram(s_defaultVertexShader, s_fragmentUniformLoopsSupported))
156 	, m_fragmentDynamicLoopsSupported	(TryCompileProgram(s_defaultVertexShader, s_fragmentDynamicLoopsSupported))
157 {
158 }
159 
split(vector<string> & dst,const string & src)160 static void split (vector<string>& dst, const string& src)
161 {
162 	size_t start = 0;
163 	size_t end	 = string::npos;
164 
165 	while ((end = src.find(' ', start)) != string::npos)
166 	{
167 		dst.push_back(src.substr(start, end-start));
168 		start = end+1;
169 	}
170 
171 	if (start < end)
172 		dst.push_back(src.substr(start, end-start));
173 }
174 
operator ()(const RenderContext & context) const175 set<int> GetCompressedTextureFormats::operator() (const RenderContext& context) const
176 {
177 	const glw::Functions& gl = context.getFunctions();
178 
179 	int numFormats = 0;
180 	gl.getIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
181 
182 	vector<int> formats(numFormats);
183 	if (numFormats > 0)
184 		gl.getIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, &formats[0]);
185 
186 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS) failed");
187 
188 	set<int> formatSet;
189 	std::copy(formats.begin(), formats.end(), std::inserter(formatSet, formatSet.begin()));
190 
191 	return formatSet;
192 }
193 
194 // ContextInfo
195 
ContextInfo(const RenderContext & context)196 ContextInfo::ContextInfo (const RenderContext& context)
197 	: m_context(context)
198 {
199 	const glw::Functions& gl = context.getFunctions();
200 
201 	if (context.getType().getAPI() == ApiType::es(2,0))
202 	{
203 		const char* result = (const char*)gl.getString(GL_EXTENSIONS);
204 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS) failed");
205 
206 		split(m_extensions, string(result));
207 	}
208 	else
209 	{
210 		int				numExtensions	= 0;
211 
212 		gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
213 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS) failed");
214 
215 		m_extensions.resize(numExtensions);
216 		for (int ndx = 0; ndx < numExtensions; ndx++)
217 			m_extensions[ndx] = (const char*)gl.getStringi(GL_EXTENSIONS, ndx);
218 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS, ndx) failed");
219 	}
220 }
221 
~ContextInfo(void)222 ContextInfo::~ContextInfo (void)
223 {
224 }
225 
getInt(int param) const226 int ContextInfo::getInt (int param) const
227 {
228 	int val = -1;
229 	m_context.getFunctions().getIntegerv(param, &val);
230 	GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetIntegerv() failed");
231 	return val;
232 }
233 
getBool(int param) const234 bool ContextInfo::getBool (int param) const
235 {
236 	glw::GLboolean val = GL_FALSE;
237 	m_context.getFunctions().getBooleanv(param, &val);
238 	GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetBooleanv() failed");
239 	return val != GL_FALSE;
240 }
241 
getString(int param) const242 const char* ContextInfo::getString (int param) const
243 {
244 	const char* str = (const char*)m_context.getFunctions().getString(param);
245 	GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetString() failed");
246 	return str;
247 }
248 
isCompressedTextureFormatSupported(int format) const249 bool ContextInfo::isCompressedTextureFormatSupported (int format) const
250 {
251 	const set<int>& formats = m_compressedTextureFormats.getValue(m_context);
252 	return formats.find(format) != formats.end();
253 }
254 
isExtensionSupported(const char * name) const255 bool ContextInfo::isExtensionSupported (const char* name) const
256 {
257 	const std::vector<std::string>& extensions = getExtensions();
258 	return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
259 }
260 
isES3Compatible() const261 bool ContextInfo::isES3Compatible() const
262 {
263    return IsES3Compatible(m_context.getFunctions());
264 }
265 
create(const RenderContext & context)266 ContextInfo* ContextInfo::create (const RenderContext& context)
267 {
268 	// ES2 uses special variant that checks support for various shader features
269 	// by trying to compile shader programs.
270 	if (context.getType().getAPI() == ApiType::es(2,0))
271 		return new ES2ContextInfo(context);
272 
273 	return new ContextInfo(context);
274 }
275 
276 } // glu
277