blob: a7e0eed5abfc9035383f475e9f7c312edd3ec05e [file] [log] [blame]
Jarkko Poyry3c827362014-09-02 11:48:52 +03001/*-------------------------------------------------------------------------
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
33using std::vector;
34using std::string;
35using std::set;
36
37namespace glu
38{
39
40class TryCompileProgram
41{
42public:
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
58private:
59 const char* m_vertexSource;
60 const char* m_fragmentSource;
61};
62
63typedef CachedValue<bool, TryCompileProgram> IsProgramSupported;
64
Graeme Leese7d1658b2019-10-07 17:55:57 +010065bool 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
Jarkko Poyry3c827362014-09-02 11:48:52 +030076// ES2-specific context info
77class ES2ContextInfo : public ContextInfo
78{
79public:
80 ES2ContextInfo (const RenderContext& context);
81 ~ES2ContextInfo (void) {}
82
83 bool isVertexUniformLoopSupported (void) const { return m_vertexUniformLoopsSupported.getValue(m_context); }
84 bool isVertexDynamicLoopSupported (void) const { return m_vertexDynamicLoopsSupported.getValue(m_context); }
85 bool isFragmentHighPrecisionSupported (void) const { return m_fragmentHighPrecisionSupported.getValue(m_context); }
86 bool isFragmentUniformLoopSupported (void) const { return m_fragmentUniformLoopsSupported.getValue(m_context); }
87 bool isFragmentDynamicLoopSupported (void) const { return m_fragmentDynamicLoopsSupported.getValue(m_context); }
88
89private:
90 IsProgramSupported m_vertexUniformLoopsSupported;
91 IsProgramSupported m_vertexDynamicLoopsSupported;
92
93 IsProgramSupported m_fragmentHighPrecisionSupported;
94 IsProgramSupported m_fragmentUniformLoopsSupported;
95 IsProgramSupported m_fragmentDynamicLoopsSupported;
96};
97
98static const char* s_defaultVertexShader =
99 "attribute highp vec4 a_position;\n"
100 "void main (void) {\n"
101 " gl_Position = a_position;\n"
102 "}\n";
103static const char* s_defaultFragmentShader =
104 "void main (void) {\n"
105 " gl_FragColor = vec4(1.0);\n"
106 "}\n";
107
108static 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";
116static 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
126static 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";
132static 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";
140static 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
150ES2ContextInfo::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
160static 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
Jarkko Poyry3c827362014-09-02 11:48:52 +0300175set<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
196ContextInfo::ContextInfo (const RenderContext& context)
197 : m_context(context)
198{
Mika Isojärvi460696f2016-02-11 16:19:58 -0800199 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 }
Jarkko Poyry3c827362014-09-02 11:48:52 +0300220}
221
222ContextInfo::~ContextInfo (void)
223{
224}
225
226int 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
234bool 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
242const 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
249bool 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
255bool 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
Emmanuel Tanguy96d4f7b2019-10-07 13:49:25 +0100261bool ContextInfo::isES3Compatible() const
262{
Graeme Leese7d1658b2019-10-07 17:55:57 +0100263 return IsES3Compatible(m_context.getFunctions());
Emmanuel Tanguy96d4f7b2019-10-07 13:49:25 +0100264}
265
Jarkko Poyry3c827362014-09-02 11:48:52 +0300266ContextInfo* 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