1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES Utilities
3e5c31af7Sopenharmony_ci * ------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Context Info Class.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp"
25e5c31af7Sopenharmony_ci#include "gluRenderContext.hpp"
26e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
27e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
28e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_ci#include <iterator>
31e5c31af7Sopenharmony_ci#include <algorithm>
32e5c31af7Sopenharmony_ci
33e5c31af7Sopenharmony_ciusing std::vector;
34e5c31af7Sopenharmony_ciusing std::string;
35e5c31af7Sopenharmony_ciusing std::set;
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_cinamespace glu
38e5c31af7Sopenharmony_ci{
39e5c31af7Sopenharmony_ci
40e5c31af7Sopenharmony_ciclass TryCompileProgram
41e5c31af7Sopenharmony_ci{
42e5c31af7Sopenharmony_cipublic:
43e5c31af7Sopenharmony_ci	// \note Assumes that shader pointer can be stored as is (eg. it is static data)
44e5c31af7Sopenharmony_ci	TryCompileProgram (const char* vertexSource, const char* fragmentSource)
45e5c31af7Sopenharmony_ci		: m_vertexSource	(vertexSource)
46e5c31af7Sopenharmony_ci		, m_fragmentSource	(fragmentSource)
47e5c31af7Sopenharmony_ci	{
48e5c31af7Sopenharmony_ci	}
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_ci	bool operator() (const RenderContext& context) const
51e5c31af7Sopenharmony_ci	{
52e5c31af7Sopenharmony_ci		ShaderProgram program(context,
53e5c31af7Sopenharmony_ci			ProgramSources() << VertexSource(m_vertexSource)
54e5c31af7Sopenharmony_ci							 << FragmentSource(m_fragmentSource));
55e5c31af7Sopenharmony_ci		return program.isOk();
56e5c31af7Sopenharmony_ci	}
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ciprivate:
59e5c31af7Sopenharmony_ci	const char*	m_vertexSource;
60e5c31af7Sopenharmony_ci	const char*	m_fragmentSource;
61e5c31af7Sopenharmony_ci};
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_citypedef CachedValue<bool, TryCompileProgram> IsProgramSupported;
64e5c31af7Sopenharmony_ci
65e5c31af7Sopenharmony_cibool IsES3Compatible(const glw::Functions& gl)
66e5c31af7Sopenharmony_ci{
67e5c31af7Sopenharmony_ci	// Detect compatible GLES context by querying GL_MAJOR_VERSION.
68e5c31af7Sopenharmony_ci	// This query does not exist on GLES2 so succeeding query implies GLES3+ context.
69e5c31af7Sopenharmony_ci	glw::GLint majorVersion = 0;
70e5c31af7Sopenharmony_ci	gl.getError();
71e5c31af7Sopenharmony_ci	gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
72e5c31af7Sopenharmony_ci
73e5c31af7Sopenharmony_ci	return (gl.getError() == GL_NO_ERROR);
74e5c31af7Sopenharmony_ci}
75e5c31af7Sopenharmony_ci
76e5c31af7Sopenharmony_ci// ES2-specific context info
77e5c31af7Sopenharmony_ciclass ES2ContextInfo : public ContextInfo
78e5c31af7Sopenharmony_ci{
79e5c31af7Sopenharmony_cipublic:
80e5c31af7Sopenharmony_ci										ES2ContextInfo						(const RenderContext& context);
81e5c31af7Sopenharmony_ci										~ES2ContextInfo						(void) {}
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ci	bool								isVertexUniformLoopSupported		(void) const	{ return m_vertexUniformLoopsSupported.getValue(m_context);		}
84e5c31af7Sopenharmony_ci	bool								isVertexDynamicLoopSupported		(void) const	{ return m_vertexDynamicLoopsSupported.getValue(m_context);		}
85e5c31af7Sopenharmony_ci	bool								isFragmentHighPrecisionSupported	(void) const	{ return m_fragmentHighPrecisionSupported.getValue(m_context);	}
86e5c31af7Sopenharmony_ci	bool								isFragmentUniformLoopSupported		(void) const	{ return m_fragmentUniformLoopsSupported.getValue(m_context);	}
87e5c31af7Sopenharmony_ci	bool								isFragmentDynamicLoopSupported		(void) const	{ return m_fragmentDynamicLoopsSupported.getValue(m_context);	}
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ciprivate:
90e5c31af7Sopenharmony_ci	IsProgramSupported					m_vertexUniformLoopsSupported;
91e5c31af7Sopenharmony_ci	IsProgramSupported					m_vertexDynamicLoopsSupported;
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_ci	IsProgramSupported					m_fragmentHighPrecisionSupported;
94e5c31af7Sopenharmony_ci	IsProgramSupported					m_fragmentUniformLoopsSupported;
95e5c31af7Sopenharmony_ci	IsProgramSupported					m_fragmentDynamicLoopsSupported;
96e5c31af7Sopenharmony_ci};
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_cistatic const char* s_defaultVertexShader =
99e5c31af7Sopenharmony_ci	"attribute highp vec4 a_position;\n"
100e5c31af7Sopenharmony_ci	"void main (void) {\n"
101e5c31af7Sopenharmony_ci	"	gl_Position = a_position;\n"
102e5c31af7Sopenharmony_ci	"}\n";
103e5c31af7Sopenharmony_cistatic const char* s_defaultFragmentShader =
104e5c31af7Sopenharmony_ci	"void main (void) {\n"
105e5c31af7Sopenharmony_ci	"	gl_FragColor = vec4(1.0);\n"
106e5c31af7Sopenharmony_ci	"}\n";
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_cistatic const char* s_vertexUniformLoopsSupported =
109e5c31af7Sopenharmony_ci	"attribute highp vec4	a_position;\n"
110e5c31af7Sopenharmony_ci	"uniform int			u_numIters;\n"
111e5c31af7Sopenharmony_ci	"void main (void) {\n"
112e5c31af7Sopenharmony_ci	"	gl_Position = a_position;\n"
113e5c31af7Sopenharmony_ci	"	for (int i = 0; i < u_numIters; i++)\n"
114e5c31af7Sopenharmony_ci	"		gl_Position += vec4(0.1);\n"
115e5c31af7Sopenharmony_ci	"}\n";
116e5c31af7Sopenharmony_cistatic const char* s_vertexDynamicLoopsSupported =
117e5c31af7Sopenharmony_ci	"attribute highp vec4	a_position;\n"
118e5c31af7Sopenharmony_ci	"uniform mediump float	a, b;\n"
119e5c31af7Sopenharmony_ci	"void main (void) {\n"
120e5c31af7Sopenharmony_ci	"	gl_Position = a_position;\n"
121e5c31af7Sopenharmony_ci	"	int numIters = a < b ? int(3.0*b) : int(a_position.x);\n"
122e5c31af7Sopenharmony_ci	"	for (int i = 0; i < numIters; i++)\n"
123e5c31af7Sopenharmony_ci	"		gl_Position += vec4(0.1);\n"
124e5c31af7Sopenharmony_ci	"}\n";
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_cistatic const char* s_fragmentHighPrecisionSupported =
127e5c31af7Sopenharmony_ci	"varying highp vec4		v_color;\n"
128e5c31af7Sopenharmony_ci	"void main (void) {\n"
129e5c31af7Sopenharmony_ci	"	highp float tmp = v_color.r;\n"
130e5c31af7Sopenharmony_ci	"	gl_FragColor = v_color;\n"
131e5c31af7Sopenharmony_ci	"}\n";
132e5c31af7Sopenharmony_cistatic const char* s_fragmentUniformLoopsSupported =
133e5c31af7Sopenharmony_ci	"varying mediump vec4	v_color;\n"
134e5c31af7Sopenharmony_ci	"uniform int			u_numIters;\n"
135e5c31af7Sopenharmony_ci	"void main (void) {\n"
136e5c31af7Sopenharmony_ci	"	gl_FragColor = v_color;\n"
137e5c31af7Sopenharmony_ci	"	for (int i = 0; i < u_numIters; i++)\n"
138e5c31af7Sopenharmony_ci	"		gl_FragColor += vec4(0.1);\n"
139e5c31af7Sopenharmony_ci	"}\n";
140e5c31af7Sopenharmony_cistatic const char* s_fragmentDynamicLoopsSupported =
141e5c31af7Sopenharmony_ci	"varying mediump vec4	v_color;\n"
142e5c31af7Sopenharmony_ci	"uniform mediump float	a, b;\n"
143e5c31af7Sopenharmony_ci	"void main (void) {\n"
144e5c31af7Sopenharmony_ci	"	gl_FragColor = v_color;\n"
145e5c31af7Sopenharmony_ci	"	int numIters = a < b ? int(3.0*b) : int(v_color.x);\n"
146e5c31af7Sopenharmony_ci	"	for (int i = 0; i < numIters; i++)\n"
147e5c31af7Sopenharmony_ci	"		gl_FragColor += vec4(0.1);\n"
148e5c31af7Sopenharmony_ci	"}\n";
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_ciES2ContextInfo::ES2ContextInfo (const RenderContext& context)
151e5c31af7Sopenharmony_ci	: glu::ContextInfo					(context)
152e5c31af7Sopenharmony_ci	, m_vertexUniformLoopsSupported		(TryCompileProgram(s_vertexUniformLoopsSupported, s_defaultFragmentShader))
153e5c31af7Sopenharmony_ci	, m_vertexDynamicLoopsSupported		(TryCompileProgram(s_vertexDynamicLoopsSupported, s_defaultFragmentShader))
154e5c31af7Sopenharmony_ci	, m_fragmentHighPrecisionSupported	(TryCompileProgram(s_defaultVertexShader, s_fragmentHighPrecisionSupported))
155e5c31af7Sopenharmony_ci	, m_fragmentUniformLoopsSupported	(TryCompileProgram(s_defaultVertexShader, s_fragmentUniformLoopsSupported))
156e5c31af7Sopenharmony_ci	, m_fragmentDynamicLoopsSupported	(TryCompileProgram(s_defaultVertexShader, s_fragmentDynamicLoopsSupported))
157e5c31af7Sopenharmony_ci{
158e5c31af7Sopenharmony_ci}
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_cistatic void split (vector<string>& dst, const string& src)
161e5c31af7Sopenharmony_ci{
162e5c31af7Sopenharmony_ci	size_t start = 0;
163e5c31af7Sopenharmony_ci	size_t end	 = string::npos;
164e5c31af7Sopenharmony_ci
165e5c31af7Sopenharmony_ci	while ((end = src.find(' ', start)) != string::npos)
166e5c31af7Sopenharmony_ci	{
167e5c31af7Sopenharmony_ci		dst.push_back(src.substr(start, end-start));
168e5c31af7Sopenharmony_ci		start = end+1;
169e5c31af7Sopenharmony_ci	}
170e5c31af7Sopenharmony_ci
171e5c31af7Sopenharmony_ci	if (start < end)
172e5c31af7Sopenharmony_ci		dst.push_back(src.substr(start, end-start));
173e5c31af7Sopenharmony_ci}
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_ciset<int> GetCompressedTextureFormats::operator() (const RenderContext& context) const
176e5c31af7Sopenharmony_ci{
177e5c31af7Sopenharmony_ci	const glw::Functions& gl = context.getFunctions();
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_ci	int numFormats = 0;
180e5c31af7Sopenharmony_ci	gl.getIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ci	vector<int> formats(numFormats);
183e5c31af7Sopenharmony_ci	if (numFormats > 0)
184e5c31af7Sopenharmony_ci		gl.getIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, &formats[0]);
185e5c31af7Sopenharmony_ci
186e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS) failed");
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci	set<int> formatSet;
189e5c31af7Sopenharmony_ci	std::copy(formats.begin(), formats.end(), std::inserter(formatSet, formatSet.begin()));
190e5c31af7Sopenharmony_ci
191e5c31af7Sopenharmony_ci	return formatSet;
192e5c31af7Sopenharmony_ci}
193e5c31af7Sopenharmony_ci
194e5c31af7Sopenharmony_ci// ContextInfo
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_ciContextInfo::ContextInfo (const RenderContext& context)
197e5c31af7Sopenharmony_ci	: m_context(context)
198e5c31af7Sopenharmony_ci{
199e5c31af7Sopenharmony_ci	const glw::Functions& gl = context.getFunctions();
200e5c31af7Sopenharmony_ci
201e5c31af7Sopenharmony_ci	if (context.getType().getAPI() == ApiType::es(2,0))
202e5c31af7Sopenharmony_ci	{
203e5c31af7Sopenharmony_ci		const char* result = (const char*)gl.getString(GL_EXTENSIONS);
204e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS) failed");
205e5c31af7Sopenharmony_ci
206e5c31af7Sopenharmony_ci		split(m_extensions, string(result));
207e5c31af7Sopenharmony_ci	}
208e5c31af7Sopenharmony_ci	else
209e5c31af7Sopenharmony_ci	{
210e5c31af7Sopenharmony_ci		int				numExtensions	= 0;
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci		gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
213e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS) failed");
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_ci		m_extensions.resize(numExtensions);
216e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < numExtensions; ndx++)
217e5c31af7Sopenharmony_ci			m_extensions[ndx] = (const char*)gl.getStringi(GL_EXTENSIONS, ndx);
218e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS, ndx) failed");
219e5c31af7Sopenharmony_ci	}
220e5c31af7Sopenharmony_ci}
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_ciContextInfo::~ContextInfo (void)
223e5c31af7Sopenharmony_ci{
224e5c31af7Sopenharmony_ci}
225e5c31af7Sopenharmony_ci
226e5c31af7Sopenharmony_ciint ContextInfo::getInt (int param) const
227e5c31af7Sopenharmony_ci{
228e5c31af7Sopenharmony_ci	int val = -1;
229e5c31af7Sopenharmony_ci	m_context.getFunctions().getIntegerv(param, &val);
230e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetIntegerv() failed");
231e5c31af7Sopenharmony_ci	return val;
232e5c31af7Sopenharmony_ci}
233e5c31af7Sopenharmony_ci
234e5c31af7Sopenharmony_cibool ContextInfo::getBool (int param) const
235e5c31af7Sopenharmony_ci{
236e5c31af7Sopenharmony_ci	glw::GLboolean val = GL_FALSE;
237e5c31af7Sopenharmony_ci	m_context.getFunctions().getBooleanv(param, &val);
238e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetBooleanv() failed");
239e5c31af7Sopenharmony_ci	return val != GL_FALSE;
240e5c31af7Sopenharmony_ci}
241e5c31af7Sopenharmony_ci
242e5c31af7Sopenharmony_ciconst char* ContextInfo::getString (int param) const
243e5c31af7Sopenharmony_ci{
244e5c31af7Sopenharmony_ci	const char* str = (const char*)m_context.getFunctions().getString(param);
245e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetString() failed");
246e5c31af7Sopenharmony_ci	return str;
247e5c31af7Sopenharmony_ci}
248e5c31af7Sopenharmony_ci
249e5c31af7Sopenharmony_cibool ContextInfo::isCompressedTextureFormatSupported (int format) const
250e5c31af7Sopenharmony_ci{
251e5c31af7Sopenharmony_ci	const set<int>& formats = m_compressedTextureFormats.getValue(m_context);
252e5c31af7Sopenharmony_ci	return formats.find(format) != formats.end();
253e5c31af7Sopenharmony_ci}
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_cibool ContextInfo::isExtensionSupported (const char* name) const
256e5c31af7Sopenharmony_ci{
257e5c31af7Sopenharmony_ci	const std::vector<std::string>& extensions = getExtensions();
258e5c31af7Sopenharmony_ci	return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
259e5c31af7Sopenharmony_ci}
260e5c31af7Sopenharmony_ci
261e5c31af7Sopenharmony_cibool ContextInfo::isES3Compatible() const
262e5c31af7Sopenharmony_ci{
263e5c31af7Sopenharmony_ci   return IsES3Compatible(m_context.getFunctions());
264e5c31af7Sopenharmony_ci}
265e5c31af7Sopenharmony_ci
266e5c31af7Sopenharmony_ciContextInfo* ContextInfo::create (const RenderContext& context)
267e5c31af7Sopenharmony_ci{
268e5c31af7Sopenharmony_ci	// ES2 uses special variant that checks support for various shader features
269e5c31af7Sopenharmony_ci	// by trying to compile shader programs.
270e5c31af7Sopenharmony_ci	if (context.getType().getAPI() == ApiType::es(2,0))
271e5c31af7Sopenharmony_ci		return new ES2ContextInfo(context);
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ci	return new ContextInfo(context);
274e5c31af7Sopenharmony_ci}
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ci} // glu
277